Manish Paul
Manish Paul

Reputation: 541

Flutter: Show different widget conditionally

I'm making an app where I want to show a progress indicator before the API returns some data. If there is any data on the API call then I want to show Widget-A or else Widget-B. But I'm not sure how to show Widget-B.

I'm only able to do the following so far...

list!.isNotEmpty
          ? ListView.builder(
              itemCount: list!["filtered"]["data"].length,
              itemBuilder: (_, index) {
                return ListTile(
                  title: Text(
                      '${list!["filtered"]["data"][index]["strikePrice"]}'),
                );
              },
            )
          : LinearProgressIndicator(),
    );

Here ListView.builder() is Widget-A and a button would be Widget-B, which IDK how to show if list is empty.

Can you help me achieve this? TIA.

Upvotes: 1

Views: 1163

Answers (4)

Luis A. Chaglla
Luis A. Chaglla

Reputation: 600

You could track if it's loading or not like this:

class _NiftyScreenState extends State<NiftyScreen> {
  Map<String, dynamic>? niftyDetails = {};
  late bool isLoading;

  @override
  void initState() {
    super.initState();
    getNiftyDetails();
  }

  getNiftyDetails() async {
    setState(() {
      isLoading = true;
    });
    try {
      this.niftyDetails = await fetchNiftyData();
    catch (err) {
      print(err);
      // Here you can save the error message if you want to show it
    }
    setState(() {
      isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: isLoading
          ? LinearProgressIndicator()
          : niftyDetails!.isNotEmpty
              ? ListView.builder(
                  itemCount: niftyDetails!["filtered"]["data"].length,
                  itemBuilder: (_, index) {
                    return ListTile(
                      title: Text(
                          '${niftyDetails!["filtered"]["data"][index]["strikePrice"]}'),
                    );
                  },
                )
              : WidgetB(),
    );
  }
}

Upvotes: 2

Amani Saaduddin
Amani Saaduddin

Reputation: 458

Take a boolean variable, let's say bool _isLoading; Just before you trigger your API call set it to true setState(() { _isLoading = true });, then as soon as you receive response from your API set the boolean value to false setState(() { _isLoading = false});. Lastly,

 !_isLoading?  
        list!.isNotEmpty
          ? ListView.builder(
              itemCount: list!["filtered"]["data"].length,
              itemBuilder: (_, index) {
                return ListTile(
                  title: Text(
                      '${list!["filtered"]["data"][index]["strikePrice"]}'),
                );
              },
            )
          : Container(
            child: Text("list is empty"), // show whatever you'd like to when list is empty
          ) 
        : LinearProgressIndicator(),
    );

Upvotes: 1

Allan C
Allan C

Reputation: 95

  1. One way of doing is by setting a variable before the condition.

    Widget widgetToShow = (some condition) ? widgetA : WidgetB;

    list!.isNotEmpty ? widgetToShow : LinearProgressIndicator(), );

  2. or just use one variable for everything, using IF of CASE statements to handle 3 possible widgets(A, B and ProgressIndicator).

Upvotes: 0

Dr Younss AIT MOU
Dr Younss AIT MOU

Reputation: 1117

Or you could use a layout builder

list!.isNotEmpty
  ? LayoutBuilder(
    builder: (BuildContext context, BoxConstraints constraints) {
      final remoteList = list!["filtered"]["data"];
      if (remoteList.isNotEmpty) {
        return ListView.builder(
          itemCount: list!["filtered"]["data"].length,
          itemBuilder: (_, index) {
            return ListTile(
            title: Text(
            '${list!["filtered"]["data"][index]["strikePrice"]}'),
            );
          },
        );
      } else {
        return WidgetB();
      }
    },
    ),
  : LinearProgressIndicator(),

Upvotes: 0

Related Questions