Jihad Naji
Jihad Naji

Reputation: 311

How to add tabs dynamically to TabBar in Flutter?

How do I add tabs dynamically to the TabBar Widget in Flutter? The list of tabs is fetched from the internet using a REST API.

When I fetch the list using the code below I get the following errors:

RangeError (index): Invalid value: Only valid value is 0: 1

A RenderFlex overflowed by 99896 pixels on the bottom.

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  Future<List<Categories>> categoriesList;

  final categoryTabs = <Tab>[
    Tab(text: 'Home'),
  ];

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

    categoriesList = NewsServices.fetchCategoriesList(lang: 'en');
    categoriesList.then((categories) {
      categories.forEach((category) {
        setState(() {
          categoryTabs.add(Tab(
            text: category.name,
          ));
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: categoryTabs.length,
      child: Scaffold(
        appBar: AppBar(
          title: Text('Example App'),
          bottom: TabBar(
            isScrollable: true,
            tabs: categoryTabs,
          ),
        ),
        body: SafeArea(...),
        ),
      ),
    );
  }

App demo for the error on iOS simulator

Upvotes: 1

Views: 2196

Answers (1)

Md Khairul Islam
Md Khairul Islam

Reputation: 627

You have to iterate the list which you achieved from the REST API.

Suppose, we declare a list of String which you will get from the REST API.

List<String> tabTextList;

Then declare the list of tabs.

List<Tab> _tabs = List<Tab>();

Then iterate the list of strings.

List<Tab> getTabs() {
    _tabs.clear();
    for (int i = 0; i < tabTextList.length; i++) {
      _tabs.add(getTab(i));
    }
    return _tabs;
  }

  Tab getTab(int widgetNumber) {
    return Tab(
      text: "${tabTextList[widgetNumber]}",
    );
  }

Then the build function will be like this.

@override
 Widget build(BuildContext context) {
   return Scaffold(
      body: DefaultTabController(
        length: tabTextList.length,
        child: Scaffold(
          
            bottom: TabBar(
              isScrollable: true,
              tabs: getTabs(),
            ),
          ),
          
          body: Container(),
        ),
      ),
    );
 }

According to your updated code you have to change some portion.

Use another variable categoryTabsTemp to store the array temporarily. After that you have to use setState to update the categoryTabs and rebuild. The updated code should be like that.

var categoryTabs = <Tab>[
    Tab(text: 'Home'),
  ];

  var categoryTabsTemp = <Tab>[
    Tab(text: 'Home'),
  ];

  @override
  void initState() {
    super.initState();
    categoriesList = NewsServices.fetchCategoriesList(lang: 'en');
    categoriesList.then((categories) {
      categories.forEach((category) {
        categoryTabsTemp.add(Tab(
          text: category.name,
        ));
      });
      setState(() {
        categoryTabs = categoryTabsTemp;
      });
    });
  }

Upvotes: 4

Related Questions