Flutter Web and PaginatedDataTable
Tags: productivity, webdev, flutter, dart
Published: 2020-06-13 14:53:21

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

<!-- wp:paragraph -->
<p>We will cover briefly about</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li><strong>PaginatedDataTable..</strong></li><li><strong>CustomPaginatedTable (Wrapper over PaginatedDataTable)</strong></li></ol>
<!-- /wp:list -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><strong>Note: For changes to data, we have used Provider….This article won’t be explaining how the changes gets notified….</strong></p></blockquote>
<!-- /wp:quote -->

{% youtube Tw9LSJCpQMs %}

<!-- wp:paragraph -->
<p>Introducing PaginatedDataTable….</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*x2RceF7sJ_FLRXSJFJbZUA.png" alt="Flutter Web and PaginatedDataTable"/><figcaption>Flutter Web and PaginatedDataTable</figcaption></figure>
<!-- /wp:image -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Hosted URL&nbsp;: <a href="https://fir-signin-4477d.firebaseapp.com/#/" rel="noreferrer noopener" target="_blank">https://fir-signin-4477d.firebaseapp.com/#/</a></p></blockquote>
<!-- /wp:quote -->

####Article here: https://flatteredwithflutter.com/using-paginateddatatable-in-flutter-web/

<!-- wp:paragraph -->
<p>As per the documentation&nbsp;:</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>A material design data table that shows data using multiple pages.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>A paginated data table shows <a href="https://api.flutter.dev/flutter/material/PaginatedDataTable/rowsPerPage.html" rel="noreferrer noopener" target="_blank">rowsPerPage</a> rows of data per page and provides controls for showing other pages.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Data is read lazily from from a <a href="https://api.flutter.dev/flutter/material/DataTableSource-class.html" rel="noreferrer noopener" target="_blank">DataTableSource</a>.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p><strong>Note&nbsp;: Data is read lazily, which means the widget is already respective performance optimization….</strong></p>
<!-- /wp:paragraph -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:paragraph -->
<p>For this article, we have created a custom widget called <strong>CustomPaginatedTable..(</strong>Basically a wrapper over<strong> PaginatedDataTable)..</strong></p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*rJdA98PMp108kGZvIPcLuQ.png" alt=""/><figcaption>Flutter Web and PaginatedDataTable…</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>This is the structure of our <strong>CustomPaginatedTable. </strong>We have kept some defaults inside the latter lines of our constructor…</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In case, you want to just see a sample table, you can</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">@override<br>Widget build(BuildContext context) {<br>    return CustomPaginatedTable();<br>}</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>This will initialize the paginatedDataTable with default data and source…</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4><strong>Fetching data to&nbsp;show..</strong></h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>We have used sample rest api service…</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><a href="https://jsonplaceholder.typicode.com/users" rel="noreferrer noopener" target="_blank">https://jsonplaceholder.typicode.com/users</a></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>This gives us a list of 10 users…Then we have moulded the response into a <strong>UserModel</strong>..</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Now, to show the usermodel in the <strong>CustomPaginatedTable</strong>, we need to</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Specify <strong>dataColumns (this takes in a list)</strong></li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>For instance,</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">&lt;DataColumn&gt;[<br>        DataColumn(<br>          label: Text(DataTableConstants.colPhone),<br>          tooltip: DataTableConstants.colPhone,<br>        ),<br>        DataColumn(<br>          label: Text(DataTableConstants.colWebsite),<br>          tooltip: DataTableConstants.colWebsite,<br>        ),<br>        DataColumn(<br>          label: Text(DataTableConstants.otherDetails),<br>          tooltip: DataTableConstants.otherDetails,<br>        ),<br>];</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Output :</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*Kk1kSbgczQeCFK4HzEZZog.png" alt="Flutter Web and PaginatedDataTable.."/><figcaption>Flutter Web and PaginatedDataTable..</figcaption></figure>
<!-- /wp:image -->

<!-- wp:list -->
<ul><li>Specify <strong>dataSource (</strong>this takes in a class extending<a href="https://api.flutter.dev/flutter/material/DataTableSource-class.html" rel="noreferrer noopener" target="_blank"><strong>DataTableSource</strong></a><strong>)</strong></li></ul>
<!-- /wp:list -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note&nbsp;: This is responsible for showing the rows inside the datatable…and by default implements notifyListeners.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>We create a class called <strong>UserDataTableSource,</strong></p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*SFxZD_m4rhqKoneWG_GQpw.png" alt="Flutter Web and PaginatedDataTable.."/><figcaption>Flutter Web and PaginatedDataTable..</figcaption></figure>
<!-- /wp:image -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">UserDataTableSource({<br>    @required List&lt;UserModel&gt; userData,<br>})  : _userData = userData,<br>        assert(userData != null);</pre>
<!-- /wp:preformatted -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">final List&lt;UserModel&gt; _userData;</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>We will pass the list of UserModel to our <strong>UserDataTableSource</strong></p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Showing the rows of data,</li></ul>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">DataRow getRow(int index){<br> // IMPLEMENT HERE<br>}</pre>
<!-- /wp:preformatted -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">@override<br>int get rowCount =&gt; _userData.length;</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>For each index, we will parse the desired values as</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*81nHXo95ewmUtyrpc-cc-A.png" alt="Flutter Web and PaginatedDataTable.."/><figcaption>Flutter Web and PaginatedDataTable..</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p><strong>NOTE : Number of DataCell (here) and DataColumn (see above step), should be same..</strong></p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*baHrr7F7y6b5YeN1syE-Yg.png" alt="Flutter Web and PaginatedDataTable.."/><figcaption>Flutter Web and PaginatedDataTable..</figcaption></figure>
<!-- /wp:image -->

<!-- wp:heading {"level":4} -->
<h4>Implement Sorting&nbsp;…</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Most of the time, we might want to sort the data, for instance, in this example.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>We want to sort by email, name and id..</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Lets implement our sorting logic..</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*5h-Bj6UjvuwMLff-zv7j4w.png" alt="Flutter Web and PaginatedDataTable.."/><figcaption>Flutter Web and PaginatedDataTable..</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Create a method called <strong>sort</strong>, inside the <strong>UserDataTableSource…</strong></p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><strong>getField&nbsp;:</strong> What type of field (present in the UserModel), you want to sort</p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><strong>ascending&nbsp;: </strong>sort by asc or desc</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Lets go back to the <strong>dataColumns</strong>&nbsp;, where we have a list…</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">DataColumn(<br>      label: Text(DataTableConstants.colID),<br>      numeric: true,<br>      tooltip: DataTableConstants.colID,<br>      onSort: (colIndex, asc) {<br>            _sort&lt;num&gt;((user) =&gt; user.id, colIndex, asc, _src, _provider);<br>      },<br> ),</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>there is a property in <strong>DataColumn</strong> called <a href="https://api.flutter.dev/flutter/material/DataColumn/onSort.html" rel="noreferrer noopener" target="_blank"><strong>onSort</strong></a>..</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In our main class, we need to have our own function, where we specify</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">void _sort&lt;T&gt;(<br>    Comparable&lt;T&gt; Function(UserModel user) getField,<br>    int colIndex,<br>    bool asc,<br>    UserDataTableSource _src,<br>    UserDataNotifier _provider,<br>  ) {<br>    _src.sort&lt;T&gt;(getField, asc);<br>    _provider.sortAscending = asc;<br>    _provider.sortColumnIndex = colIndex;<br>  }</pre>
<!-- /wp:preformatted -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note&nbsp;: The above fxn (<strong>_sort</strong>) is a private one, (only accessible from our class), and in turn calls the UserDataTableSource’s <strong>sort</strong></p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Time to implement this inside our DataColumns (Name, id and email)…</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*zuh_blnCGIrobtK4DzYXGA.png" alt="Flutter Web and PaginatedDataTable.."/><figcaption>Flutter Web and PaginatedDataTable..</figcaption></figure>
<!-- /wp:image -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:paragraph -->
<p>For <strong>id</strong>, we specify type as <strong>num</strong>… For <strong>name/email,</strong> we specify as <strong>String…</strong></p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>And now we can sort…..</p></blockquote>
<!-- /wp:quote -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading {"level":4} -->
<h4>RowsPerPage</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Inside our CustomPaginatedTable, we have a property called <strong>onRowChanged. </strong>This basically binds to the <a href="https://api.flutter.dev/flutter/material/PaginatedDataTable/onRowsPerPageChanged.html" rel="noreferrer noopener" target="_blank"><strong>onRowsPerPageChanged</strong></a> property of <strong>PaginatedDataTable..</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>First we set the value of <strong>rowsPerPage (property) </strong>to a default value</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><a href="https://api.flutter.dev/flutter/material/PaginatedDataTable/defaultRowsPerPage-constant.html" rel="noreferrer noopener" target="_blank">PaginatedDataTable.defaultRowsPerPage</a></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>and when we want to change the value, we call the fxn <strong>onRowChanged and pass in the selected value..</strong></p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">onRowChanged: (index) =&gt; _provider.rowsPerPage = index,<br>rowsPerPage: _provider.rowsPerPage,</pre>
<!-- /wp:preformatted -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*QRG68ZDv2GS0TpLXeOTE7A.png" alt="Rows per page…."/><figcaption>Rows per page….</figcaption></figure>
<!-- /wp:image -->

<!-- wp:heading {"level":4} -->
<h4>Actions on DataTable…</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In order to show actions (refresh in our case), we specify (in our <strong>CustomPaginatedTable</strong>)</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">showActions: true,</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>and for the type of action, we set</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">actions: &lt;IconButton&gt;[<br>        IconButton(<br>          splashColor: Colors.transparent,<br>          icon: const Icon(Icons.refresh),<br>          onPressed: () {<br>            _provider.fetchData();<br>            _showSBar(context, DataTableConstants.refresh);<br>          },<br>        ),<br>],</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>This shows the following <strong>refresh icon </strong>(top right) :</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*8u9YtR29Xz2NmNlR2g8Ddw.png" alt="Refresh Icon (Top right)…."/><figcaption>Refresh Icon (Top right)….</figcaption></figure>
<!-- /wp:image -->

<!-- wp:heading {"level":4} -->
<h4>View Other&nbsp;Details</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Sometimes, we want to hide extra details, and show only if user requests. For that we have the <strong>OtherDetails</strong> field..</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>There is an <strong>icon(reverse triangle)</strong> associated with each row,..</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">DataCell(<br>     IconButton(<br>            hoverColor: Colors.transparent,<br>            splashColor: Colors.transparent,<br>            icon: const Icon(Icons.details),<br>            onPressed: () =&gt; onRowSelect(index),<br>     ),<br>),</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>and on the click of the icon, we open a dialog and show that row’s details..</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">UserDataTableSource(<br>      onRowSelect: (index) =&gt; _showDetails(context, _model[index]),<br>      userData: _model,<br>);</pre>
<!-- /wp:preformatted -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">void _showDetails(BuildContext c, UserModel data) async =&gt;<br>      await showDialog&lt;bool&gt;(<br>        context: c,<br>        builder: (_) =&gt; CustomDialog(<br>          showPadding: false,<br>          child: OtherDetails(data: data),<br>      ),<br>);</pre>
<!-- /wp:preformatted -->

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Hosted URL&nbsp;: <a href="https://fir-signin-4477d.firebaseapp.com/#/" rel="noreferrer noopener" target="_blank">https://fir-signin-4477d.firebaseapp.com/#/</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><a href="https://github.com/AseemWangoo/experiments_with_web" rel="noreferrer noopener" target="_blank">Source code for Flutter Web App..</a></p></blockquote>
<!-- /wp:quote -->

{% youtube Tw9LSJCpQMs %}