DataTable is a really useful widget in Flutter. Today we will look into how we can use that to create beautiful
apps in Flutter for Android and iOS.
Watch Demo
Below is the demo of the app we are going to make.
Watch Video Tutorial
The video tutorial demonstrates all the functions that I am going to describe below.
You can watch the video tutorial to see it in action.
Let’s jump into the code. Start by adding the DataTable widget to your UI.
Add DataTable widget
DataTable( columns:[], rows:[], ... )
I am writing a method called dataBody() to return the DataTable widget that we add it to the main UI.
we will see it later.
Colums represent the header of the DataTable. Rows should be the same number as columns or empty.
We are going to display a list of users.
Create a new file named “user.dart” and create a class ‘User’. We will have two member variables ‘firstName’ and ‘lastName’.
Also a constructor and a function that returns a list of users.
user.dart
class User { String firstName; String lastName; User({this.firstName, this.lastName}); static List<User> getUsers() { return <User>[ User(firstName: "Aaryan", lastName: "Shah"), User(firstName: "Ben", lastName: "John"), User(firstName: "Carrie", lastName: "Brown"), User(firstName: "Deep", lastName: "Sen"), User(firstName: "Emily", lastName: "Jane"), ]; } }
Get the users and initialize the State in the main UI.
// Add these to your main UI file.
List<User> users; List<User> selectedUsers; bool sort; @override void initState() { sort = false; selectedUsers = []; users = User.getUsers(); super.initState(); } ...
Set the Columns or Headers for Table
columns: [ DataColumn( label: Text("FIRST NAME"), numeric: false, tooltip: "This is First Name", ), DataColumn( label: Text("LAST NAME"), numeric: false, tooltip: "This is Last Name", ), ], ...
Map Users to Rows
rows: users .map( (user) => DataRow( selected: selectedUsers.contains(user), onSelectChanged: (b) { print("Onselect"); onSelectedRow(b, user); }, cells: [ DataCell( Text(user.firstName), onTap: () { print('Selected ${user.firstName}'); }, ), DataCell( Text(user.lastName), ), ]), ) .toList(), ...
Sort the table
We are going to sort the table based on the firstName.
We are going to use the ‘sortAscending’ and ‘sortColumnIndex’ to the DataTable.
Since we know that firstName is the ‘0’th index, we are setting ‘sortColumnIndex’ to zero.
DataTable( sortAscending: sort, sortColumnIndex: 0, ...
implement the onSort function for each DataColumn.
Declare a bool variable ‘sort’ which we will be toggling when user clicks on the ‘firstName’ header, we will toggle the ‘sort’ variable.
you can see the initialisation above in the initState.
DataColumn( label: Text("FIRST NAME"), numeric: false, tooltip: "This is First Name", onSort: (columnIndex, ascending) { setState(() { sort = !sort; }); onSortColum(columnIndex, ascending); }), ), ...
Then call the onSortColumn that we are going to write inside the onSort() method.
onSortColum(int columnIndex, bool ascending) { if (columnIndex == 0) { if (ascending) { users.sort((a, b) => a.firstName.compareTo(b.firstName)); } else { users.sort((a, b) => b.firstName.compareTo(a.firstName)); } } }
‘ascending’ will toggle when we update the ‘sort’ variable using setState() inside the onSort function.
Add the Checkbox
implement ‘onSelectChanged’ method for each row which will be called each time user clicks on the row
and ‘selected’ property to true selects all the checkboxes. Checkboxes will appear for each row when you add this method. But our aim to select the Checkbox for user we select, correct?
We have a variable ‘selectedUsers’ variable declared early which I am initialising in the initState() above.
onSelectedRow(bool selected, User user) async { setState(() { if (selected) { selectedUsers.add(user); } else { selectedUsers.remove(user); } }); }
If the user clicks the row and if the selected is true, we will add them to ‘selectedUsers’ list.
and update selected to
DataRow( selected: selectedUsers.contains(user), onSelectChanged: (b) { print("Onselect"); onSelectedRow(b, user); }, ...
When user click on each row, we will check if the added to the list and set the selected property with true or false like below.
‘true’ makes the user Checkbox selected.
selected: selectedUsers.contains(user), makes it true or false which makes the Checkbox corresponding to each user checked or not.
DataRow( selected: selectedUsers.contains(user), onSelectChanged: (b) { print("Onselect"); onSelectedRow(b, user); }, ...
Delete Users
I am going to add two buttons just below the DataTable, once shows the number of selected users and the other will call a method to delete Selected SUers.
Let’s write the delete method.
deleteSelected() async { setState(() { if (selectedUsers.isNotEmpty) { List<User> temp = []; temp.addAll(selectedUsers); for (User user in temp) { users.remove(user); selectedUsers.remove(user); } } }); }
We will add the DataTable inside the ‘SingleChildScrollView’ and add that inside the ‘Expanded’ Widget to prevent the overflow.
Complete Example
import 'package:flutter/material.dart'; import 'user.dart'; class DataTableDemo extends StatefulWidget { DataTableDemo() : super(); final String title = "Data Table Flutter Demo"; @override DataTableDemoState createState() => DataTableDemoState(); } class DataTableDemoState extends State<DataTableDemo> { List<User> users; List<User> selectedUsers; bool sort; @override void initState() { sort = false; selectedUsers = []; users = User.getUsers(); super.initState(); } onSortColum(int columnIndex, bool ascending) { if (columnIndex == 0) { if (ascending) { users.sort((a, b) => a.firstName.compareTo(b.firstName)); } else { users.sort((a, b) => b.firstName.compareTo(a.firstName)); } } } onSelectedRow(bool selected, User user) async { setState(() { if (selected) { selectedUsers.add(user); } else { selectedUsers.remove(user); } }); } deleteSelected() async { setState(() { if (selectedUsers.isNotEmpty) { List<User> temp = []; temp.addAll(selectedUsers); for (User user in temp) { users.remove(user); selectedUsers.remove(user); } } }); } SingleChildScrollView dataBody() { return SingleChildScrollView( scrollDirection: Axis.vertical, child: DataTable( sortAscending: sort, sortColumnIndex: 0, columns: [ DataColumn( label: Text("FIRST NAME"), numeric: false, tooltip: "This is First Name", onSort: (columnIndex, ascending) { setState(() { sort = !sort; }); onSortColum(columnIndex, ascending); }), DataColumn( label: Text("LAST NAME"), numeric: false, tooltip: "This is Last Name", ), ], rows: users .map( (user) => DataRow( selected: selectedUsers.contains(user), onSelectChanged: (b) { print("Onselect"); onSelectedRow(b, user); }, cells: [ DataCell( Text(user.firstName), onTap: () { print('Selected ${user.firstName}'); }, ), DataCell( Text(user.lastName), ), ]), ) .toList(), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, verticalDirection: VerticalDirection.down, children: <Widget>[ Expanded( child: dataBody(), ), Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: <Widget>[ Padding( padding: EdgeInsets.all(20.0), child: OutlineButton( child: Text('SELECTED ${selectedUsers.length}'), onPressed: () {}, ), ), Padding( padding: EdgeInsets.all(20.0), child: OutlineButton( child: Text('DELETE SELECTED'), onPressed: selectedUsers.isEmpty ? null : () { deleteSelected(); }, ), ), ], ), ], ), ); } }
That’s all about DataTables. Watch the video tutorial to see it in action.
Hope you understood everything about DataTables in Flutter. Please leave your valuable comments below.
I will be happy to clear as per my knowledge.
Thanks for reading.
This tutorial is amazing, it’s just what i need to know how tu use DataTable easily . Thanks .
So Can you help us with a second step like Use a Json Data from an API (php mysql) to display it in a DataTable.
Pingback: Flutter DataTable + MySQL – MOBILE PROGRAMMING
It says no main method found how do I go about fixing that
Go to the main.dart file, import your file and add to the ‘home’ property inside the main method.
How can I dynamically add new names to this list
Ashher, its shown in the article. When you add more objects to the array and call setState on it, the UI will be refreshed.
This is really amazing. One can easily have an idea about the data table.
Great job.
Thank you
Pingback: #Google's Flutter Tutorials - Data Tables (coderzheaven.com) - TutsFx