How to populate DataTable widget with data fetched from my API?

563 views Asked by At

So I try the code from following stack overflow answer How to populate DataTable with JSON API in flutter, and changed that as per my need but DataTable is not populated and displaying my error message "No data found...". I'm adding whatever I've tried so, it will be easy whoever have worked with DataTable in past.

Thank you in advance.

  List applicants = [];
  String applicantsByDate = "http://localhost:3000/applicants/getApplicantsByDate";

  DataRow _resultsAPI(index, data) {
    return DataRow(
      cells: <DataCell>[
        DataCell(
          Text(
            data['id'],
          ),
        ), //add name of your columns here
        DataCell(
          Text(
            data['firstName'],
          ),
        ),
        DataCell(
          Text(
            data['lastName'],
          ),
        ),
        DataCell(
          Text(
            data['createdAt'],
          ),
        )
      ],
    );
  }

 Future<List?> fetchApplicants() async {
      http.Response response = await http.get(Uri.parse(applicantsByDate));
      if (response.statusCode == 200) {
        var data = jsonDecode(response.body);
        setState(() {
          applicants = data['applicantsByDate'];
        });
        return jsonDecode(response.body);
      }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        leading: Padding(
          padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
          child: Image.asset(
              "images/Logo.png",
              fit: BoxFit.cover,
              height: 20.00,
              width: 20.00),
        ),
        leadingWidth: 130,
        title: const Text('Applicants'),
      ),
      body: SingleChildScrollView(
        child: SafeArea(
          child: Container(
            padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
            child: FutureBuilder(
              future: fetchApplicants(),
              builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
                if (snapshot.hasData) {
                  applicants = snapshot.data;
                  if (applicants.length != 0) {
                    return Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        const SizedBox(
                          height: 30.0,
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.start,
                          children: <Widget>[
                            Expanded(
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                children: [
                                  DataTable(
                                    columns: const [
                                      DataColumn(
                                        label: Text(
                                          'ID',
                                          style: TextStyle(
                                              color: Palette.coloresCRC,
                                              fontWeight: FontWeight.w600,
                                              fontSize: 18),
                                        ),
                                      ),
                                      DataColumn(
                                        label: Text(
                                          'First Name',
                                          style: TextStyle(
                                              color: Palette.coloresCRC,
                                              fontWeight: FontWeight.w600,
                                              fontSize: 18),
                                        ),
                                      ),
                                      DataColumn(
                                        label: Text(
                                          'Last Name',
                                          style: TextStyle(
                                              color: Palette.coloresCRC,
                                              fontWeight: FontWeight.w600,
                                              fontSize: 18),
                                        ),
                                      ),
                                      DataColumn(
                                        label: Text(
                                          'Date Applied',
                                          style: TextStyle(
                                              color: Palette.coloresCRC,
                                              fontWeight: FontWeight.w600,
                                              fontSize: 18),
                                        ),
                                      ),
                                    ],
                                    rows: List.generate(
                                      applicants.length,
                                      (index) => _resultsAPI(
                                        index,
                                        applicants[index],
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ],
                        ),
                      ],
                    );
                  } else {
                    return Row(
                      children: const <Widget>[
                        SizedBox(
                          // ignore: sort_child_properties_last
                          child: CircularProgressIndicator(),
                          width: 30,
                          height: 30,
                        ),
                        Padding(
                          padding: EdgeInsets.all(40),
                          child: Text('No Data Found...'),
                        ),
                      ],
                    );
                  }
                } else {
                  return Row(
                    children: const <Widget>[
                      SizedBox(
                        // ignore: sort_child_properties_last
                        child: CircularProgressIndicator(),
                        width: 30,
                        height: 30,
                      ),
                      Padding(
                        padding: EdgeInsets.all(40),
                        child: Text('No Data Found...'),
                      ),
                    ],
                  );
                }
              },
            ),
          ),
        ),
      ),
    );
  }
}

EDIT: Here is what Im getting from my API call, it works as it should

   {
        "applicantsByDate": [
            {
                "id": 1007,
                "firstName": "Andrea",
                "lastName": "Savillon",
                "createdAt": "2022-12-14T19:58:57.431Z"
            },
            {
                "id": 1006,
                "firstName": "Emily",
                "lastName": "Savillon",
                "createdAt": "2022-12-14T19:56:42.795Z"
            },
            {
                "id": 1005,
                "firstName": "Andres",
                "lastName": "Abadie",
                "createdAt": "2022-12-14T19:54:03.424Z"
            },
            {
                "id": 1004,
                "firstName": "Carlos",
                "lastName": "Marroquin",
                "createdAt": "2022-12-14T18:05:42.157Z"
            },
            {
                "id": 1003,
                "firstName": "Sara",
                "lastName": "Savillon",
                "createdAt": "2022-12-14T18:03:41.343Z"
            },
            {
                "id": 1002,
                "firstName": "Alexander",
                "lastName": "Savillon",
                "createdAt": "2022-12-14T17:28:38.909Z"
            },
            {
                "id": 2,
                "firstName": "Miguel",
                "lastName": "Madrid",
                "createdAt": "2022-12-13T21:59:48.593Z"
            },
            {
                "id": 1,
                "firstName": "Eder",
                "lastName": "Savillon",
                "createdAt": "2022-12-13T14:54:42.118Z"
            }
        ]
    }
1

There are 1 answers

2
Alejandro Cumpa On BEST ANSWER

There are somethings that I would change in your code and yor API response:

  1. In your API response, this record has another structure: "primerNombre" y "primerApellido"

    {
       "id": 1004,
       "primerNombre": "Carlos",
       "primerApellido": "Marroquin",
       "createdAt": "2022-12-14T18:05:42.157Z"
    }
    
  2. Another important point is the return of your fetchApplicants() function, why would you process the data and return the raw? and your FutureBuilder is especting a List not a Map(data).

    Future<List?> fetchApplicants() async {
       http.Response response = await http.get(Uri.parse(applicantsByDate));
       if (response.statusCode == 200) {
         var data = jsonDecode(response.body);
         applicants = data['applicantsByDate'];
         return applicants;
       }
    

    }

  3. In the _resultsAPI function you must retrieve a String for the content of the Text() widget so you should use: data['id'].toString()

I've copied your string to locally and make it work: enter image description here

The full code should look something like this:

class ResulstsScreen extends StatelessWidget {
  ResulstsScreen({super.key});

  List applicants = [];

  String applicantsByDate =
      "http://localhost:3000/applicants/getApplicantsByDate";

  DataRow _resultsAPI(index, data) {
    return DataRow(
      cells: <DataCell>[
        DataCell(
          Text(
            data['id'],
          ),
        ), //add name of your columns here
        DataCell(
          Text(
            data['firstName'],
          ),
        ),
        DataCell(
          Text(
            data['lastName'],
          ),
        ),
        DataCell(
          Text(
            data['createdAt'],
          ),
        )
      ],
    );
  }

  Future<List?> fetchApplicants() async {
    //var data = jsonDecode(
        //'{"applicantsByDate": [{"id": 1007,"firstName": "Andrea","lastName": "Savillon","createdAt": "2022-12-14T19:58:57.431Z"},{"id": 1006,"firstName": "Emily","lastName": "Savillon","createdAt": "2022-12-14T19:56:42.795Z"},{"id": 1005,"firstName": "Andres","lastName": "Abadie","createdAt": "2022-12-14T19:54:03.424Z"},{"id": 1004,"firstName": "Carlos","lastName": "Marroquin","createdAt": "2022-12-14T18:05:42.157Z"},{"id": 1003,"firstName": "Sara","lastName": "Savillon","createdAt": "2022-12-14T18:03:41.343Z"},{"id": 1002,"firstName": "Alexander","lastName": "Savillon","createdAt": "2022-12-14T17:28:38.909Z"},{"id": 2,"firstName": "Miguel","lastName": "Madrid","createdAt": "2022-12-13T21:59:48.593Z"},{"id": 1,"firstName": "Eder","lastName": "Savillon","createdAt": "2022-12-13T14:54:42.118Z"}]}');

     http.Response response = await http.get(Uri.parse(applicantsByDate));
      if (response.statusCode == 200) {
        var data = jsonDecode(response.body);
      
    applicants = data['applicantsByDate'];
    return applicants;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        leading: Padding(
          padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
          child: Image.asset("images/Logo.png",
              fit: BoxFit.cover, height: 20.00, width: 20.00),
        ),
        leadingWidth: 130,
        title: const Text('Applicants'),
      ),
      body: SingleChildScrollView(
        child: SafeArea(
          child: Container(
            padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
            child: FutureBuilder(
              future: fetchApplicants(),
              builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
                if (snapshot.hasData) {
                  applicants = snapshot.data;
                  if (applicants.length != 0) {
                    return Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        const SizedBox(
                          height: 30.0,
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.start,
                          children: <Widget>[
                            Expanded(
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                children: [
                                  DataTable(
                                    columns: const [
                                      DataColumn(
                                        label: Text(
                                          'ID',
                                          style: TextStyle(
                                              color: Colors.black,
                                              fontWeight: FontWeight.w600,
                                              fontSize: 18),
                                        ),
                                      ),
                                      DataColumn(
                                        label: Text(
                                          'First Name',
                                          style: TextStyle(
                                              color: Colors.black,
                                              fontWeight: FontWeight.w600,
                                              fontSize: 18),
                                        ),
                                      ),
                                      DataColumn(
                                        label: Text(
                                          'Last Name',
                                          style: TextStyle(
                                              color: Colors.black,
                                              fontWeight: FontWeight.w600,
                                              fontSize: 18),
                                        ),
                                      ),
                                      DataColumn(
                                        label: Text(
                                          'Date Applied',
                                          style: TextStyle(
                                              color: Colors.black,
                                              fontWeight: FontWeight.w600,
                                              fontSize: 18),
                                        ),
                                      ),
                                    ],
                                    rows: List.generate(
                                      applicants.length,
                                      (index) => _resultsAPI(
                                        index,
                                        applicants[index],
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ],
                        ),
                      ],
                    );
                  } else {
                    return Row(
                      children: const <Widget>[
                        SizedBox(
                          // ignore: sort_child_properties_last
                          child: CircularProgressIndicator(),
                          width: 30,
                          height: 30,
                        ),
                        Padding(
                          padding: EdgeInsets.all(40),
                          child: Text('No Data Found...'),
                        ),
                      ],
                    );
                  }
                } else {
                  return Row(
                    children: const <Widget>[
                      SizedBox(
                        // ignore: sort_child_properties_last
                        child: CircularProgressIndicator(),
                        width: 30,
                        height: 30,
                      ),
                      Padding(
                        padding: EdgeInsets.all(40),
                        child: Text('No Data Found...'),
                      ),
                    ],
                  );
                }
              },
            ),
          ),
        ),
      ),
    );
  }
}