Flutter Error: Use api in tabbar and tabbarView?

Issue

I want to fetch data from API and use the data in tabbar and tabview.

I want to create (Ayurved app), I have a list of subcategory in the api, I followed this documentation, so I need to add api’s subcategory to my TabBar.
So How can I do that? I don’t understand how this will happen.
This is my Tab Page.

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:hospital/customApiVariable.dart';
import 'package:http/http.dart' as http;

class TabPage extends StatefulWidget {
  final medicineCatUniqId;
  const TabPage({Key key, this.medicineCatUniqId}) : super(key: key);
  // const TabPage({Key key}) : super(key: key);

  @override
  _TabPageState createState() => _TabPageState();
}

class _TabPageState extends State<TabPage> {
  var response;
  var medicineSubCategoryApi;

  @override
  void initState() {
    // TODO: implement initState
    //
    super.initState();
// for loading
    fetchData(widget.medicineCatUniqId);
  }

  fetchData(var medicineCatUniqId) async {
a2rTokenKey=carpet1234');
    var api = Uri.parse(
        '$baseUrl/productSubCatApi.php?a2rTokenKey=$a2rTokenKey&pcat=$medicineCatUniqId');
    response = await http.get(
      api,
    );

    print("medicineCatApiLnk " + api.toString());
    print("medicineCat" + response.body);

    medicineSubCategoryApi = jsonDecode(response.body);
    print("medicineCatString" + medicineSubCategoryApi.toString());
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: medicineSubCategoryApi.length,
        child: Scaffold(

          appBar: AppBar(
            title: const Text('Tabbed AppBar'),
            bottom: TabBar(
              isScrollable: true,

              tabs: medicineSubCategoryApi.map((choice) {
                return Tab(
                  text: choice.psubCatName,
                  icon: Icon(choice),

                );
              }).toList(),
            ),
          ),

          body: TabBarView(
            children: medicineSubCategoryApi.map<Widget>((choice) {
              return Padding(
                padding: const EdgeInsets.all(20.0),
                child: ChoicePage(

                  choice: choice,
                ),
              );
            }).toList(),
          ),
        ),
      ),

    );
  }
}

class ChoicePage extends StatelessWidget {
  const ChoicePage({Key key, this.choice}) : super(key: key);
  final choice;


  @override
  Widget build(BuildContext context) {
    final TextStyle textStyle = Theme.of(context).textTheme.display1;
    return Card(
      color: Colors.white,
      child: Center(

        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            // Icon(
            //   choice,
            //   size: 150.0,
            //   color: textStyle.color,
            // ),
            Text(
              choice.psubCatName,

              style: textStyle,
            ),
          ],
        ),
      ),
    );

  }
}

This is my Api Data.

[{"psubCatUniq":"60c464556cd04","psubCatName":"TURMERIC CAPSULES","psubCatDescrition":"TURMERIC CAPSULES","psubCatImg":"http:\/\/a2rstore.com\/inventory\/images\/subCategory-bb.jpg","psubCatIcon":"","psubCatDate":"","psubCatlink":"list.php?subName=TURMERIC CAPSULES&sub=60c464556cd04","pcatUniq":"60c462501a664","pcatName":"Herbal Tablets"},{"psubCatUniq":"60c464360de3f","psubCatName":"PAIN CALM TABLET","psubCatDescrition":"PAIN CALM TABLET","psubCatImg":"http:\/\/a2rstore.com\/inventory\/images\/subCategory-aa.jpg","psubCatIcon":"","psubCatDate":"","psubCatlink":"list.php?subName=PAIN CALM TABLET&sub=60c464360de3f","pcatUniq":"60c462501a664","pcatName":"Herbal Tablets"}]

Solution

You can use a FutureBuilder widget to make the API call then access the data you require from the response data to create the Tabs.

A Simple Example


@override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FutureBuilder(
        future: fetchData(widget.medicineCatUniqId),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            // API data will be stored as snapshot.data 
            return  DefaultTabController(
              // Your Widget UI here ( Copy & paste ) what you have above
            );
          } else if (snapshot.hasError) {
            return Text('Error');
          } else {
            return Text('Loading');
          }
        }
      ),
    );
  }

You will also need to update fetchData() to return the value to FutureBuilder:


fetchData(var medicineCatUniqId) async {
    var api = Uri.parse(
        '$baseUrl/productSubCatApi.php?a2rTokenKey=$a2rTokenKey&pcat=$medicineCatUniqId');
    response = await http.get(
      api,
    );

    print("medicineCatApiLnk " + api.toString());
    print("medicineCat" + response.body);

    medicineSubCategoryApi = jsonDecode(response.body);
    print("medicineCatString" + medicineSubCategoryApi.toString());
    //setState(() {});
   
    return medicineSubCategoryApi;
  }

Answered By – Rohan Thacker

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *