How to use conditional statement within child attribute of a Flutter Widget (Center Widget)

384,280

Solution 1

Actually you can use if/else and switch and any other statement inline in dart / flutter.

Use an immediate anonymous function

class StatmentExample extends StatelessWidget {
  Widget build(BuildContext context) {
    return Text((() {
      if(true){
        return "tis true";}

      return "anything but true";
    })());
  }
}

ie wrap your statements in a function

(() {
  // your code here
}())

I would heavily recommend against putting too much logic directly with your UI 'markup' but I found that type inference in Dart needs a little bit of work so it can be sometimes useful in scenarios like that.

Use the ternary operator

condition ? Text("True") : null,

Use If or For statements or spread operators in collections

children: [
  ...manyItems,
  oneItem,
  if(canIKickIt)
    ...kickTheCan
  for (item in items)
    Text(item)

Use a method

child: getWidget()

Widget getWidget() {
  if (x > 5) ...
  //more logic here and return a Widget

Redefine switch statement

As another alternative to the ternary operator, you could create a function version of the switch statement such as in the following post https://stackoverflow.com/a/57390589/1058292.

  child: case2(myInput,
  {
    1: Text("Its one"),
    2: Text("Its two"),
  }, Text("Default"));

Solution 2

I personally use if/else statement in children with this kind of block statement. It only supports on Dart version 2.3.0 above.

if / else

Column(
    children: [
        if (_selectedIndex == 0) ...[
          DayScreen(),
        ] else ...[
          StatsScreen(),
        ],
    ],
 ),

if / else if

Column(
    children: [
        if (_selectedIndex == 0) ...[
          DayScreen(),
        ] else if(_selectedIndex == 1)...[
          StatsScreen(),
        ],
    ],
 ),

multiple widgets example

Column(
    children: [
        if (_selectedIndex == 0) ...[
          DayScreen(),
          AboutScreen(),
          InfoScreen(),
        ] else if(_selectedIndex == 1)...[
          HomeScreen(),
          StatsScreen(),
        ],
    ],
 ),

Solution 3

In Dart, if/else and switch are statements not expressions. They don't return a value so you can't pass them to constructor params. If you have a lot of conditional logic in your build method, then it is a good practice to try and simplify it. For example, you can move self-contained logic to methods, and use if/else statements to initialize local variables which you can later use.

Using a method and if/else

Widget _buildChild() {
  if (condition) {
    return ...
  }
  return ...
}

Widget build(BuildContext context) {
  return new Container(child: _buildChild());
}

Using an if/else

Widget build(BuildContext context) {
  Widget child;
  if (condition) {
    child = ...
  } else {
    child = ...
  }
  return new Container(child: child);
}

Solution 4

In such a case I would recommand using the ternary operator:

child: condition ? Container() : Center()

and try to avoid code of the form:

if (condition) return A else return B

which is needlessly more verbose than the ternary operator.

But if more logic is needed you may also:

Use the Builder widget

The Builder widget is meant for allowing the use of a closure when a child widget is required:

A platonic widget that calls a closure to obtain its child widget.

It is convenient anytime you need logic to build a widget, it avoids the need to create a dedicated function.

You use the Builder widget as the child, you provide your logic in its builder method:

Center(
  child: Builder(
    builder: (context) {
      // any logic needed...
      final condition = _whateverLogicNeeded();
      
      return condition
          ? Container();
          : Center();
    }
  )
)

The Builder provides a convenient place to hold the creational logic. It is more straightforward than the immediate anonymous function proposed by atreeon.

Also I agree that the logic should be extracted from the UI code, but when it's really UI logic it is sometimes more legible to keep it there.

Solution 5

For the record, Dart 2.3 added the ability to use if/else statements in Collection literals. This is now done the following way:

return Column(children: <Widget>[
  Text("hello"),
  if (condition)
     Text("should not render if false"),
  Text("world")
],);

Flutter Issue #28181 - Inline conditional rendering in list

Share:
384,280

Related videos on Youtube

Marko
Author by

Marko

Updated on July 08, 2022

Comments

  • Marko
    Marko almost 2 years

    So far whenever I needed to use a conditional statement within a Widget I have done the following (Using Center and Containers as simplified dummy examples):

    new Center(
      child: condition == true ? new Container() : new Container()
    )
    

    Though when I tried using an if/else statement it would lead to an Dead code warning:

    new Center(
      child: 
        if(condition == true){
          new Container();
        }else{
          new Container();
        }
    )
    

    Interestingly enough I tried with a switch case statement and it gives me the same warning and thus I cannot run the code. Am I doing something wrong or is it so that one cannot use if/else or switch statements without flutter thinking there is dead code?

    • Shady Aziza
      Shady Aziza about 6 years
      If you want to insert a block where widgets should be instantiated you probably better build your widget in class methods
    • Avnish Nishad
      Avnish Nishad almost 4 years
      Center( child:Builder(builder:(context){ if(true) return widget1(); else return widget2(); }) )
  • ardi
    ardi about 5 years
    How to using it
  • Ajay Kumar
    Ajay Kumar almost 5 years
    I tried this and worked for me the exact way. Thanks
  • exequielc
    exequielc almost 5 years
    condition? Text("True"): null, this does an error Asertion false in console, on runtime execution
  • otto
    otto almost 5 years
    @exequielc you must add .where(notNull).toList() and the end of the WidgetList and the method bool notNull(Object o) => o != null;. Try whole example...
  • Brett Sutton
    Brett Sutton almost 5 years
    As of Dart 2.3 to conditionally include a widget in a list you can use: [Text("Hello"), if(world) Text("World")]
  • Aseem
    Aseem over 4 years
    I have dart 2.5 but I get error running above code. It says ` this code is required to be compatible with earlier versions. try updating SDK constraints`
  • Haojen
    Haojen over 4 years
    emmm, interesting~
  • Matthew Rideout
    Matthew Rideout over 4 years
    Just a note if anyone gets stuck, if you are using Provider to rebuild your widgets on global state change, and you are getting data via "Provider.of", your conditional statement may not be re-evaluated until some other action rebuilds your widget. You need to be getting your conditional variable via "Consumer" that is being returned to the Widget build function, then your conditional statement should be properly re-evaluated as global state changes.
  • princebillyGK
    princebillyGK over 4 years
    Do they add for loop feature? if so how to implement it?
  • yN.
    yN. about 4 years
  • TechAurelian
    TechAurelian about 4 years
    Doesn't work with a single widget like AppBar -> leading: or child:
  • cwhisperer
    cwhisperer about 4 years
    What if there is no else condition? In Columns, saying a==b?c:null will not work
  • Afinas EM
    Afinas EM about 4 years
    You can simply use SizedBox.shrick() as the second widget. updating the answer.
  • Afinas EM
    Afinas EM about 4 years
    If it is a column then you can use if condition directly without else case: `if('condition') widget()'
  • Slamit
    Slamit almost 4 years
    This should be the correct answer! Thank you for this clarification it helped me!
  • Richardd
    Richardd over 3 years
    In case someone get an error about the experiment --flow-control-collections. You just need to update your pubspec.yml environment: sdk: ">=2.2.2 <3.0.0". Then do flutter clean, and also clean the cache.
  • Quick learner
    Quick learner over 3 years
    this worked for me pretty well for drawer items click and updating body
  • Kohls
    Kohls over 3 years
    One of the best things for good practices in dart/flutter
  • Curt Eckhart
    Curt Eckhart over 3 years
    @Aseem - this is because your pubspec.yaml is probably claiming compatability with older versions of dart. Edit the sdk value to declare at least 2.3 on the low value environment: sdk: ">=2.7.0 <3.0.0"
  • Mark Rotteveel
    Mark Rotteveel over 3 years
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes.
  • Nato Boram
    Nato Boram over 3 years
    That ...[] trick is awesome. It's a detail that no other answer mentioned, but it's very useful if you want to add multiple widgets conditionally.
  • mahfuz
    mahfuz about 3 years
    Interesting! 👍
  • buncis
    buncis about 3 years
    which one is better in ternary code? using null or empty Container() ?
  • ritz
    ritz almost 3 years
    Great answer! If you have one if-else condition ternary operator should suffice but if you have multiple if-else if-else conditions or switch cases, the Builder widget should be an appropriate solution.
  • Jeppe
    Jeppe almost 3 years
    What if you have a deep tree, and conditionally want to render something in the tree? Duplicate? Or will I have to split the tree somehow?
  • jauki
    jauki almost 3 years
    where can u put the style in, by the immediate anonymous funtion? for exampe: style: TextStyle(color: Colors.white),
  • Drew
    Drew almost 3 years
    I was getting an error that Column cannot contain null values for the ternary and empty Container() was a work around
  • vin shaba
    vin shaba over 2 years
    This is the most clear explanation to using conditions in attributes
  • Jagadish Nallappa
    Jagadish Nallappa over 2 years
    Thank you very much for the explanation. Cheerio!
  • Shady Mohamed Sherif
    Shady Mohamed Sherif over 2 years
    does any one know this works starting from which version of flutter?
  • brendan
    brendan over 2 years
    @ShadyMohamedSherif which version you are using now? I started using flutter from 1.17 and it is already working since then. This is nothing special, it's just spreading a list of widgets.
  • Bakhtawar
    Bakhtawar over 2 years
    i wish i knew this way before. Many Thanks :)