Dynamically display JSON data in data table layout in flutter
Solution 1
Step 1:
[
{
"DayEnd": [
{
"ColumnWidths": "40´168´96´96´108´156",
"Headers": "SL.>´Customer< ´Balance Qty>´Amount>´Oldest / Recent ",
"FieldSeparator": "´",
"DataList": [
{
"Data": "1. ´ABD ´14 / 14.60´11,090´313 / 313",
"NextLevelZoomData": [
{
"Element": "eg7P27fbW/GmCr"
},
{
"Element": "AAA=="
}
],
"NextLevelZoomType": 2
}
]
}
]
}
]
Step 2:
class TableModel {
TableModel(this.headerData, this.rowData);
List<String> headerData;
List<List<String>> rowData;
factory TableModel.fromJson(Map<String, dynamic> json) {
return TableModel(
json['DayEnd'][0]["Headers"].split('´').toList(),
buildRowData(json),
);
}
}
List<List<String>> buildRowData(Map<String, dynamic> json){
List<List<String>> rowDataCollection = [];
json['DayEnd'][0]["DataList"].forEach((rows){
rowDataCollection.add(rows['Data'].split('´').toList());
});
return rowDataCollection;
}
Step 3:
Future<void> generateList() async {
String responseBody = await rootBundle.loadString("assets/data.json");
var list = await json.decode(responseBody).cast<Map<String, dynamic>>();
return await list
.map<TableModel>((json) => TableModel.fromJson(json))
.toList();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('DataTable'),
),
body: FutureBuilder(
future: generateList(),
builder: (context, snapShot) {
if (snapShot.data == null ||
snapShot.connectionState == ConnectionState.waiting ||
snapShot.hasError ||
snapShot.data.length == 0) {
return Container(
child: Center(child: CircularProgressIndicator()),
);
} else {
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: snapShot.data.length,
itemBuilder: (BuildContext context, int index) {
final TableModel table = snapShot.data[index];
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: table.headerData.map<DataColumn>((e) {
var columnName = e;
TextAlign align;
if (columnName.contains('<')) {
align = TextAlign.start;
columnName = columnName.replaceAll('<', '');
} else if (columnName.contains('>')) {
align = TextAlign.end;
columnName = columnName.replaceAll('>', '');
} else {
align = TextAlign.center;
}
return DataColumn(
label: Text(
columnName,
textAlign: align,
));
}).toList(),
rows: table.rowData.map<DataRow>((e) {
return DataRow(
cells: e
.map<DataCell>((e) => DataCell(Text(e)))
.toList());
}).toList(),
),
);
});
}
},
)));
}
Solution 2
use createTable() & give it list & the object must have .tojson() method
import 'package:flutter/material.dart';
// This class takes any list that its elements have .toJson method and return every list element as a table row
class TableController {
static Widget createTable(List list) {
List<TableRow> rows = [];
rows.add(_createTableHeader(list[0].toJson().keys));
for (var item in list) {
rows.add(TableRow(
children: _createTableBody(item.toJson().values),
));
}
return Padding(
padding: const EdgeInsets.all(8.0),
child: Table(border: TableBorder.all(), children: rows),
);
}
static TableRow _createTableHeader(Iterable<String> keys) {
List<Widget> elements = [];
for (String key in keys) {
elements.add(Padding(
padding: const EdgeInsets.all(4.0),
child: Text(key.toString(), overflow: TextOverflow.ellipsis),
));
}
return TableRow(
children: elements,
);
}
static List<Widget> _createTableBody(Iterable values) {
List<Widget> elements = [];
for (var value in values) {
elements.add(Padding(
padding: const EdgeInsets.all(4.0),
child: Text(value.toString(), overflow: TextOverflow.ellipsis),
));
}
return elements;
}
}
use it like this:
class Employee {
Employee({
this.id,
this.name,
this.email,
});
int id;
String name;
String email;
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"email": email,
};
}
final Employee emp = Employee(id: 1, name: 'name 1');
final Employee emp1 = Employee(id: 2, name: 'name 2');
final Employee emp2 = Employee(id: 3, name: 'name 3');
final Employee emp3 = Employee(id: 4, name: 'name 4');
final List<Employee> emps = [emp, emp2, emp1];
class TablePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: TableController.createTable(emps)),
);
}
}
Comments
-
Android_id over 1 year
I am Creating a Dynamic data table view in flutter , where the column headers and the row values are added dynamically. The data is a Json response,the header is a string array and the data to be displayed in row is also a string array .The goal is to display the data in the table view without any hardcoded values. This is how I have tried is to display the data.
return ListView.builder( shrinkWrap: true, scrollDirection: Axis.vertical, itemCount: snapshot.data.dataList.length, itemBuilder: (BuildContext context, int index){ return SingleChildScrollView( child: DataTable( columns: (snapshot.data.headerList[index] as List).map((item) => DataColumn( label:( List.generate(item.length,(index){ return Text(item[index].toString()); }) ) )).toList(), rows: (snapshot.data.dataList[index].dataList as List).map((item) => DataRow( cells:<DataCell>[ DataCell( List.generate(item.length,(index){ return Text(item[index].toString()); }) ) ])).toList(), ),
This is the JSON response
"DayEnd": { "ColumnWidths": "40´168´96´96´108´156", "Headers": "SL.>´Customer< ´Balance Qty>´Amount>´Oldest / Recent ", "FieldSeparator": "´", "DataList": [ { "Data": "1. ´ABD ´14 / 14.60´11,090´313 / 313", "NextLevelZoomData": [ { "Element": "eg7P27fbW/GmCr" }, { "Element": "AAA==" } ], "NextLevelZoomType": 2 }, { "Data": "2. ´LATA´16´7,921´20 / 9", "NextLevelZoomData": [ { "Element": "MT63z0m7piukmtJZqdZ" }, { "Element": "QT/2zE/AAA=" } ], "NextLevelZoomType": 2 }, { "Data": "3. ´ANAND´11´915´426 / 426", "NextLevelZoomData": [ { "Element": "AAA=" } ], "NextLevelZoomType": 2 }, { "Data": "4. ´Asts´1´1,010´27 / 27", "NextLevelZoomData": [ { "Element": "w/VbTHwKgQAAA==" } ], "NextLevelZoomType": 2 }, }
The above response gives a string data
Headers
which is separated by a special character "`",the each character has to be displayed in a each column header so which is converted to an array. Similarly the data as well . The column width that has to be maintained for each data is mentioned in columnWidth Similarly the alignment of the data like if "SL.>" then ">" it has to be right aligned.I am not sure if this is the right approach to get it, This gives an error
The argument type 'List<Text>' can't be assigned to the parameter type 'Widget'.
Any idea to approach in a better way will be much appreciated.