Reputation: 742
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:
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:
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
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();
}
},
)),
),
);
}
Upvotes: 4