Options
All
  • Public
  • Public/Protected
  • All
Menu

Limit rows processing

Introduction

If the processing of your rows is very expensive (like if it is fetched from an API, or requires a heavy computation), you may want to limit the number of calls to this function. For instance, if you want to automatically refresh data on text filter changes, you would avoid re-process everything on every key press.

This process of limitation is very important to reduce your load & improve performances, and it can be seen in two main variations:

debouncing
runs after a cooldown of n ms
throttling
runs at most every n ms

You can check out this nice article on CSS-Tricks for more informations about the difference between those kind of functions.

In this example, we use the _.debounce function from lodash to call processRows only when the user stop typing for 1s.

See the ajax tutorial via data function or custom handlers for a more detailed example of AJAX data querying.

Demo

{{callsCount}}

Code

Typescript

import { debounce } from 'lodash';
import Vue from 'vue';
import { IDataFnParams, IDisplayHandlerParam, ITableContentParam, TColumnsDefinition, VueDatatable } from 'vuejs-datatable';

import { IPeople } from '../utils';
import { queryApiForData } from '../utils';
declare var rows: IPeople[];

const app = new Vue( {
    el:   '#demo-app',
    data: {
        filter:  '',
        columns: [
            { label: 'ID', field: 'id', align: 'center', filterable: false },
            { label: 'Username', field: 'user.username' },
            { label: 'First Name', field: 'user.first_name' },
            { label: 'Last Name', field: 'user.last_name' },
            { label: 'Email', field: 'user.email', align: 'right', sortable: false },
            { label: 'Address', representedAs: row => `${ row.address  }, ${ row.city  }, ${ row.state }`, align: 'right', sortable: false },
        ] as TColumnsDefinition<IPeople>,
        async someLongOperation( this: VueDatatable<IPeople, any>, params: IDataFnParams<IPeople> ): Promise<ITableContentParam<IPeople>> {
            this.$root.$data.callsCount++;
            const { data, totalRows } = await queryApiForData( params );

            return {
                rows:          data,
                totalRowCount: totalRows,
            };
        },
        page:       1,
        callsCount: 0,
    },
    mounted() {
        this.$datatables.debounced.processRows = debounce( this.$datatables.debounced.processRows, 1000 );
    },
} );

HTML

<div id="demo-app">
    <div class="row">
        <div class="col-xs-12 col-md-4 form-inline">
            <div class="form-group">
                <label for="filter" class="sr-only">Filter</label>
                <input type="text" class="form-control" v-model="filter" placeholder="Filter" @keydown="$event.stopImmediatePropagation()">
            </div>
        </div>
        <label for="calls-count" class="col-xs-6 col-md-4">Process count: </label>
        <output id="calls-count" class="col-xs-6 col-md-4">{{callsCount}}</output>
        <div class="col-xs-12 table-responsive">
            <datatable :columns="columns" :data="someLongOperation" :filter="filter" name="debounced" :per-page="25"></datatable>
            <datatable-pager v-model="page" table="debounced"></datatable-pager>
        </div>
    </div>
    <div class="row">
    </div>
</div>

Generated using TypeDoc