Search code examples
flutterapitabbartabbarcontroller

How do I make a tab and tab bar view dynamic in flutter so that it will ha on the response from an api?


I am trying to create a list, add data to the list based on received responses but it is not working.

I tried to loop through the database to check data exist before adding to the list. I seem not to be doing it well.

My challenge is to dynamically control the things I add to the list. so that it will change based on that.

    Updated the codes.
      //Defualt tab controller
       DefaultTabController(
        length: tabs.length,
       child: Column(
          children: [
            Container(
              child: TabBar(
                labelColor: HexColor("#006E40"),
                unselectedLabelColor: Colors.black,
                indicatorColor: HexColor("#006E40"),
                indicatorWeight: 3,
                indicatorPadding: (EdgeInsets.symmetric(horizontal: 
                10.0)),
                isScrollable: true,
              //  controller: _tabController,
                tabs: tabs ), // tabs List 
            ),
            SizedBox(height: 15),
            Container(
              margin: const EdgeInsets.only(bottom: 20.0),
              height: MediaQuery
                  .of(context)
                  .size
                  .height * 0.8,
              child: Padding(
                padding: const EdgeInsets.only(bottom: 28.0),
                child: TabBarView(
                  children: tabsItems ), // Tab Bar List
              ),}
 // Checking whether the item already exist then adding to the list 
 //  based on result
  Lsit<DatabaseItemsPastaSelf> databaseItemsPasta = [] 

  Future readPastaItems() async {
this.databaseItemsPasta = await 
  PastaDatabaseSelf.instance.readAllItems();
   for(int i = 0; i<databaseItemsPasta.length; i++){
    if (databaseItemsPasta.length != 0) {
     tabs.add(
      Padding(
        padding: const EdgeInsets.only(top: 20),
        child: Text(
          "Fruits",
          style: TextStyle(fontWeight: FontWeight.w700, fontSize: 
               14),
            ),
          ),
        );
        tabsItems.add(PastaAndNoodlesSelf());
        break;
        }
      }
      return databaseItemsPasta.length;
      }

    List<DatabaseItemsSugarSelf> databaseItemsSugar = [];

    Future readSugarItems() async {
    this.databaseItemsSugar = await 
    SugarDatabaseSelf.instance.readAllItems();
     for(int i = 0; i<databaseItemsSugar.length; i++){
       if (databaseItemsSugar.length != 0) {
       tabs.add(
         Padding(
          padding: const EdgeInsets.only(top: 20),
           child: Text(
           "Foods",
            style: TextStyle(fontWeight: FontWeight.w700, fontSize: 
          14),
        ),
      ),
    );
     tabsItems.add(SugarSelf());
       break;
  }
   }
   return databaseItemsSugar.length;
    }


   List<Widget> tabs = [];
  List<Widget> tabsItems = [];
  }

      

Solution

  • You can use the FutureBuilder, map function, and state management as following

    FutureBuilder: listening to fetching data state. map function: to iterate throw data list. state management to update data list state.

    please update the

    readPastaItems()

    to be

    var tabIndex = 0;
    bool isLoadingData = false;
    
    List<dynamic> databaseItemsPasta = [];
    
    
    Future readPastaItems() async {
      isLoadingData = true;
      await PastaDatabaseSelf.instance.readAllItems().then((records) {
        this.databaseItemsPasta = records;
        isLoadingData = false;
      });
    }
    

    and update the

    DefaultTabController

    to be wrapped with FutureBuilder

    FutureBuilder(
    future: Future.delayed(Duration.zero, () => readPastaItems()),
    builder: (context, snapshot) {
    
      if(isLoadingData) return CircularProgressIndicator();
      if(snapshot.hasError) return Text('error');
      if(!snapshot.hasData || this.databaseItemsPasta.isEmpty) return Text('no data');
    
      if(this.databaseItemsPasta.length > 0)  return DefaultTabController(
        length: databaseItemsPasta?.length ?? 0,
        initialIndex: tabIndex,
        child: Scaffold(
          appBar: AppBar(),
          body: TabBarView(
            physics: NeverScrollableScrollPhysics(),
            children: databaseItemsPasta.map((databaseItem) =>
                Padding(padding: const EdgeInsets.only(top: 12, bottom: 12), child: Text('${databaseItem.toString()}')),
            ).toList(),
          ),
          bottomNavigationBar: TabBar(
            labelColor: Colors.black45,
            tabs: databaseItemsPasta.map((databaseItem) =>
                Padding(padding: const EdgeInsets.only(top: 12, bottom: 12), child: Text('${databaseItem.toString()}')),
            ).toList(),
          ),
        ),
      );
    
      return SizedBox();
    }
    )