Flutter Tutorials – DataTable (Android & iOS).

By | January 24, 2019

 

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.

 

8 thoughts on “Flutter Tutorials – DataTable (Android & iOS).

  1. NDRI OMER

    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.

    Reply
  2. Pingback: Flutter DataTable + MySQL – MOBILE PROGRAMMING

    1. James Post author

      Go to the main.dart file, import your file and add to the ‘home’ property inside the main method.

      Reply
    1. James Post author

      Ashher, its shown in the article. When you add more objects to the array and call setState on it, the UI will be refreshed.

      Reply
  3. Suravi

    This is really amazing. One can easily have an idea about the data table.
    Great job.
    Thank you

    Reply
  4. Pingback: #Google's Flutter Tutorials - Data Tables (coderzheaven.com) - TutsFx

Leave a Reply

Your email address will not be published. Required fields are marked *