DataTable with MobX implementation in Flutter

Abdulsamet İLERİ
Level Up Coding
Published in
4 min readFeb 20, 2021

--

Today we’re going to look at how to implement Flutter DataTable backed by MobX. We’re going to create Monthly Invoice Table. It shows personal invoices as monthly for a specific user. All necessary data we will read, it will be in a local json file specified as invoices.json in assets/ folder.

This article is not intended as an introduction of MobX. So we will assume that you already have a basic knowledge what MobX is. If not, you can read the basis on their website. I think it easy to learn and implement as against BLoC. I mean, don’t be scared to use it. :)

Firstly, we have to prepare our invoice model to parse the json as specified below. As you can see, it consists of id, date, and amount. These properties show us what the invoice will look like.

The corresponding dart class is:

This class can be created easily using the website by copying our json file. You can also use json_serializable package. For simplicity, we won’t use this package in this article.

Now let’s have a look at our view model. You can think of a view model as it contains all your application logic, api calls, business rules etc.

We will try to tell what the code do as line-by-line.

Let’s start.

Observable, Computed and Action annotations was explained greatly in their website. In a nutshell, you can think of Observable, we track annotated variable to change the ui according to their value, Computed is a derived form of the observable variable and Action is the way of mutating observable value.

@observableObservableList<ExInvoiceModel> invoices = <ExInvoiceModel>[].asObservable();

ExInvoiceModel is a superset of InvoiceModel. This class extend of InvoiceModel and adds new property called as isSelected.

isSelected is just a logic property. In order to change our checkbox and total amount card we need to track its value so we have to put observable annotation above it.

ObservableList

is a special type of list. Dart does not support Observable<T> types. These types come from the MobX package. MobX automatically observes all of the items within it. In case of adding, removing or updating an item, relevant actions will be emitted. This means that you will be informed what the changes are. Thereby you can handle it easily.

@observableObservableList<ExInvoiceModel> invoices = <ExInvoiceModel>[].asObservable();

You can also think of not required to put observable annotation over the invoices variable. Because we already indicate that the list items as observable. Actually, it’s all about your logic. If you want to track for example the case of going from null to a list with values, you have to put it. In this article, I prefer to put:

.asObservable();

is nothing but an extension method. Think of it casting from List<T> to ObservableList<T>.

@computed
List<ExInvoiceModel> get selectedInvoices => invoices.where((invoice) => invoice.isSelected).toList();

In order to calculate selected invoices’ amount, we need to define selectedInvoices variable. It’s very simple method. We will filter our array according to the isSelected value.

@computed
bool get selectedInvoicesIsEmpty => selectedInvoices.isEmpty;

We need to hide or show the footer according to the items within selectedInvoices. If no items in there, we need to hide our the amount card footer.

@computed
int get totalAmount => selectedInvoices.fold(0, (previousValue, element) => previousValue + element.amount);

The first time you can think of why we don’t use reduce method? Because we have to work on the object type. Not primary types like int, string etc. Reduce works on primary types so don’t fit our case.

fetchInvoices

Putting action on the fetchInvoices method says the MobX, thanks to this method, we will mutate the invoices variable. Please track it. If you carefully look at what the method, it is basically nothing but reading local json and decode our InvoiceModel and add our observable invoices variable. In order to get data, we need to invoke this method.

Now, we will look at our complete UI.

We will look at part-by-part.

In order to get our initial data we need to invoke fetchInvoices method in initState lifecycle.

We will need to wrap our DataTable with Observer widget. Because of we will trigger the UI our variable changes. We will map our observable list to DataRow so we need to call the map method.

Two important property in there. If you want to checkbox column in every row, we have to define onSelectedChanged. Remember that, we defined our isSelected property as observable, MobX tracks that change in that variable and trigger Observer widget so our UI refresh and we will see our change in the screen.

We will wrap our footer with observer widget. Because we need to draw our ui according to the selectedInvoices array. If our array filled items, we will need to calculate total amount. If not so we can show empty widget.

Okey, thats it. If you want to see more details you can check the source code.

--

--