Home > Software design >  Displaying widget conditionally in flutter
Displaying widget conditionally in flutter

Time:02-14

I am just writing a simple application in flutter and I came across an situation where I need to display widget conditionally. When I use the ternary operator it is working perfectly fine.

Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("I quiz you, OK?"),
        ),
        body: (_questionIndex < _questionList.length)
            ? Quiz(
                questionList: _questionList,
                questionIndex: _questionIndex,
                answerSelected: _answerSelected)
            : Result(_finalScore, _reset),
      ),
    );
  }
//Woks fine

but when I replace it with if-else block I am getting an error as

Expected an identifier.dart(missing_identifier)

Expected to find ')'.dart(expected_token)

Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("I quiz you, OK?"),
        ),
        body: if(_questionIndex < _questionList.length)
            { 
              Quiz(
                questionList: _questionList,
                questionIndex: _questionIndex,
                answerSelected: _answerSelected)
            }
            
            else
            { 
              Result(_finalScore, _reset)
            },
      ),
    );
  }
//Getting error

What could be the issue as all brackets are balanced perfectly. I know I could just use ternary operator but there might arise a situation where if-else ladder would be required.

Note: Quiz() and Result() are custom widgets.

CodePudding user response:

You cannot use a if/else statement as you did, here are several ways to do it:

body: () {
  if (_questionIndex < _questionList.length) {
    return Quiz(/* ... */);
  } else {
    return Result(/* ... */);
  }
}(),

or

body: Builder(
  builder: (context) {
    if (_questionIndex < _questionList.length) {
      return Quiz(/* ... */);
    } else {
      return Result(/* ... */);
    }
  },
),

CodePudding user response:

Use Visibility

 Visibility(
   visible:_questionIndex < _questionList.length 
   replacement:Result(/* ... */) ,
   child:Quiz(/* ... */)
 )

Or offstage:

 Offstage(
   offstage: _questionIndex < _questionList.length 
   child:Result(/* ... */)     
 ),
Offstage(
   offstage: _questionIndex >=  _questionList.length 
   child:Quiz(/* ... */)     
 )

CodePudding user response:

You can simply use the ternary operator here, like

body: _questionIndex < _questionList.length ?
    Quiz(
        questionList: _questionList,
        questionIndex: _questionIndex,
        answerSelected: _answerSelected) :
    Result(_finalScore, _reset)

In case you're not familiar with ternary operators

statement ? true : false

if the statement is true the first statement/block after ? will run, otherwise the latter one

CodePudding user response:

you can create a method returning a widget and easily return what ever you want.

  Widget func(){ 
if(_questionIndex < _questionList.length){
 return Quiz( questionList: _questionList, questionIndex: _questionIndex, answerSelected: _answerSelected);}    

    else if(_questionIndex >= _questionList.length){ 
            return  Result(_finalScore, _reset); 
            }
    else{
    //widget is must
    return Container();
    }}
            Widget build(BuildContext context) {
                return MaterialApp(
                  home: Scaffold(
                    appBar: AppBar(
                      title: Text("I quiz you, OK?"),
                    ),
                    body: func();
              }
  • Related