GrandMagus
GrandMagus

Reputation: 742

Flutter DataTable Layout

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.

Upvotes: 3

Views: 4646

Answers (1)

Balasubramani Sundaram
Balasubramani Sundaram

Reputation: 1290

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

Upvotes: 4

Related Questions