Flutter DataTable Layout

1,872

Step 1:

 Future<List<NameData>> generateList() async {
    final response =
        await http.get('https://jsonplaceholder.typicode.com/posts');

    var list = await json.decode(response.body).cast<Map<String, dynamic>>();
    return await list.map<NameData>((json) => NameData.fromJson(json)).toList();
  }

Step 2:

@override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('DataTable'),
        ),
        body: Container(
            child: FutureBuilder<List<NameData>>(
          future: generateList(),
          builder: (context, snapShot) {
            if (snapShot.hasData) {
              return SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: DataTable(
                  columns: <DataColumn>[
                    DataColumn(
                      label: Text(
                        'First Name',
                        style: TextStyle(fontStyle: FontStyle.italic),
                      ),
                    ),
                    DataColumn(
                      label: Text(
                        'Last Name',
                        style: TextStyle(fontStyle: FontStyle.italic),
                      ),
                    ),
                    DataColumn(
                      label: Text(
                        'Delete',
                        style: TextStyle(fontStyle: FontStyle.italic),
                      ),
                    ),
                  ],
                  rows: snapShot.data.map<DataRow>((e) {
                    return DataRow(
                      cells: <DataCell>[
                        DataCell(Text('${e.id}')),
                        DataCell(Text('${e.userId}')),
                        DataCell(Icon(Icons.delete)),
                      ],
                    );
                  }).toList(),
                ),
              );
            }else{
              return CircularProgressIndicator();
            }
          },
        )),
      ),
    );
  }

DataTable

Share:
1,872
GrandMagus
Author by

GrandMagus

Updated on December 27, 2022

Comments

  • GrandMagus
    GrandMagus over 1 year

    I've got some layout trouble with DataTable in Flutter with a FutureBuilder, I've called the API and naturally it will display it like this:

    enter image description here

    Understandable, since I'm building a list of tables it will return multiple tables back. I want to map out only the Rows as a List and the columns should stay the same, exactly like this:

    enter image description here

    So, the columns First Name, Last Name and Delete are always the same, it just maps out the table row cells like in the second picture above.

    Is this possible to achieve this with a DataTable using the FutureBuilder like in my example?

    I've tried using the future builder in a DataRow cell since every child of the DataCell is a Widget, but it looks really horrible and I'm not sure it is the right practice...

    Here is the code:

    The API call:

    import 'dart:async';
    import 'dart:convert';
    import 'package:http/http.dart' as http;
    import 'models/names.dart';
    
    Future<List<NameData>> fetchNames() async {
      List<NameData> names = List();
      final response = await http.get('https://jsonplaceholder.typicode.com/posts');
    
      if (response.statusCode == 200) {
        // If the server did return a 200 OK response,
        // then parse the JSON.
        var namesJson = jsonDecode(response.body);
        print(response.body);
        for (int i = 0; i < namesJson.length; i++) {
          names.add(NameData.fromJson(jsonDecode(response.body)[i]));
        }
        return names;
      } else {
        // If the server did not return a 200 OK response,
        // then throw an exception.
        throw Exception('Failed to load names');
      }
    }
    
    

    The Names model:

    import 'package:flutter/foundation.dart';
    import 'dart:core';
    
    class NameData extends ChangeNotifier {
      final int id;
      final int userId;
      final String title;
      final String body;
    
      NameData({
        this.id,
        this.userId,
        this.title,
        this.body,
      });
    
      factory NameData.fromJson(Map<String, dynamic> json) {
        return NameData(
          id: json["id"],
          userId: json["userId"],
          title: json["title"],
          body: json["body"],
        );
      }
    }
    
    

    And the Names List with the Data table:

    import 'package:flutter/material.dart';
    import 'models/names.dart';
    import 'services/name_api.dart';
    
    class NameList extends StatefulWidget {
      @override
      _NameList createState() => _NameList();
    }
    
    class _NameList extends State<NameList> {
      Future<List<NameData>> futureNames;
    
      @override
      void initState() {
        super.initState();
        futureNames = fetchNames();
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            SizedBox(
              height: 600,
              child: FutureBuilder<List<NameData>>(
                future: futureNames,
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return ListView.builder(
                      itemCount: snapshot.data.length,
                      itemBuilder: (context, index) {
                        return Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisAlignment: MainAxisAlignment.spaceAround,
                          children: [
                            SizedBox(
                              height: 12.0,
                            ),
                            Container(
                              decoration: BoxDecoration(
                                color: Colors.grey[300],
                                borderRadius: BorderRadius.all(
                                  Radius.circular(12.0),
                                ),
                              ),
                              child: SingleChildScrollView(
                                scrollDirection: Axis.horizontal,
                                child: DataTable(
                                  columns: <DataColumn>[
                                    DataColumn(
                                      label: Text(
                                        'First Name',
                                        style:
                                            TextStyle(fontStyle: FontStyle.italic),
                                      ),
                                    ),
                                    DataColumn(
                                      label: Text(
                                        'Last Name',
                                        style:
                                            TextStyle(fontStyle: FontStyle.italic),
                                      ),
                                    ),
                                    DataColumn(
                                      label: Text(
                                        'Delete',
                                        style:
                                            TextStyle(fontStyle: FontStyle.italic),
                                      ),
                                    ),
                                  ],
                                  rows: <DataRow>[
                                    DataRow(
                                      cells: <DataCell>[
                                        DataCell(
                                            Text('${snapshot.data[index].id}')),
                                        DataCell(
                                            Text('${snapshot.data[index].userId}')),
                                        DataCell(Icon(Icons.delete)),
                                      ],
                                    ),
                                  ],
                                ),
                              ),
                            ),
                            SizedBox(
                              height: 16.0,
                            ),
                          ],
                        );
                      },
                    );
                  } else if (snapshot.hasError) {
                    return Text("${snapshot.error}");
                  }
                  return Container();
                },
              ),
            ),
          ],
        );
      }
    }
    
    

    Thank you in advance for your time and help.

  • GrandMagus
    GrandMagus over 3 years
    Thank you! For reference, you solution was right on point but it still returns another table, but your answer made me realize my mistake, i just need to put the itemCount to 1! :) Thanks again!