Skip to content

Commit

Permalink
feat(NgTableParams): optimize filter debounce for in-memory data arrays
Browse files Browse the repository at this point in the history
Don't debounce filter input when binding to a small in-memory data array.

Use the filterDelayThreshold to determine what constitutes a small data array.

By optimizing this way, will mean that having to specify an explicit filterDelay value will be rare.
  • Loading branch information
ccrowhurstram committed Aug 29, 2015
1 parent 449ab62 commit 8010e07
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 47 deletions.
19 changes: 17 additions & 2 deletions src/scripts/ngTableParams.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@
defaultFilterOptions = {
filterComparator: undefined, // look for a substring match in case insensitive way
filterDelay: 750,
filterDelayThreshold: 10000, // size of data array that will trigger the filterDelay being applied
filterFilterName: undefined, // when defined overrides ngTableDefaultGetDataProvider.filterFilterName
filterFn: undefined, // when defined overrides the filter function that ngTableDefaultGetData uses
filterLayout: 'stack' // alternative: 'horizontal'
},
defaultGroupOptions = {
defaultSort: 'asc', // set to 'asc' or 'desc' to apply sorting to groups
isExpanded: true
};
},
defaultFettingsFns = getDefaultSettingFns();

this.data = [];

Expand Down Expand Up @@ -154,6 +156,10 @@
var originalDataset = settings.data;
settings = angular.extend(settings, newSettings);

if (angular.isArray(newSettings.data)) {
optimizeFilterDelay();
}

// note: using != as want null and undefined to be treated the same
var hasDatasetChanged = newSettings.hasOwnProperty('data') && (newSettings.data != originalDataset);
if (hasDatasetChanged) {
Expand Down Expand Up @@ -585,6 +591,15 @@
return !!(errParamsMemento && angular.equals(errParamsMemento, createComparableParams()));
};

function optimizeFilterDelay(){
// don't debounce by default filter input when working with small synchronous datasets
if (settings.filterOptions.filterDelay === defaultFilterOptions.filterDelay &&
settings.total <= settings.filterOptions.filterDelayThreshold &&
settings.getData === defaultFettingsFns.getData){
settings.filterOptions.filterDelay = 0;
}
}

this.reloadPages = (function() {
var currentPages;
return function(){
Expand Down Expand Up @@ -737,7 +752,7 @@
sortingIndicator: 'span'
};

this.settings(getDefaultSettingFns());
this.settings(defaultFettingsFns);
this.settings(ngTableDefaults.settings);
this.settings(baseSettings);
this.parameters(baseParameters, true);
Expand Down
126 changes: 81 additions & 45 deletions test/tableParamsSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,55 +268,91 @@ describe('NgTableParams', function () {
});
});

it('settings', function () {
var params = new NgTableParams();
describe('settings', function(){

var expectedSettings = {
$loading: false,
data: null,
total: 0,
defaultSort: 'desc',
counts: [10, 25, 50, 100],
interceptors: [],
paginationMaxBlocks: 11,
paginationMinBlocks: 5,
sortingIndicator: 'span',
filterOptions: {
filterComparator: undefined,
filterDelay: 750,
filterFilterName: undefined,
filterFn: undefined,
filterLayout: 'stack'
},
groupOptions: { defaultSort: 'asc', isExpanded: true }
};
expect(params.settings()).toEqual(jasmine.objectContaining(expectedSettings));
expect(params.settings().getData).toEqual(jasmine.any(Function));
expect(params.settings().getGroups).toEqual(jasmine.any(Function));

params = new NgTableParams({}, {
total: 100,
counts: [1,2],
groupOptions: { isExpanded: false } });

expectedSettings.total = 100;
expectedSettings.counts = [1,2];
expectedSettings.groupOptions = { defaultSort: 'asc', isExpanded: false };
expect(params.settings()).toEqual(jasmine.objectContaining(expectedSettings));
});
it('defaults', function () {
var params = new NgTableParams();

var expectedSettings = {
$loading: false,
data: null,
total: 0,
defaultSort: 'desc',
counts: [10, 25, 50, 100],
interceptors: [],
paginationMaxBlocks: 11,
paginationMinBlocks: 5,
sortingIndicator: 'span',
filterOptions: {
filterComparator: undefined,
filterDelay: 750,
filterDelayThreshold: 10000,
filterFilterName: undefined,
filterFn: undefined,
filterLayout: 'stack'
},
groupOptions: { defaultSort: 'asc', isExpanded: true }
};
expect(params.settings()).toEqual(jasmine.objectContaining(expectedSettings));
expect(params.settings().getData).toEqual(jasmine.any(Function));
expect(params.settings().getGroups).toEqual(jasmine.any(Function));

params = new NgTableParams({}, {
total: 100,
counts: [1,2],
groupOptions: { isExpanded: false } });

expectedSettings.total = 100;
expectedSettings.counts = [1,2];
expectedSettings.groupOptions = { defaultSort: 'asc', isExpanded: false };
expect(params.settings()).toEqual(jasmine.objectContaining(expectedSettings));
});

it('changing settings().data should reset page to 1', function(){
// given
var tableParams = createNgTableParams({ count: 1, page: 2 }, { data: [1,2,3]});
tableParams.reload();
scope.$digest();
expect(tableParams.page()).toBe(2); // checking assumptions

// when
tableParams.settings({ data: [1,2,3, 4]});

// then
expect(tableParams.page()).toBe(1);
});

it('should not set filterDelay when working with synchronous data', function(){
// given
var tableParams = new NgTableParams({}, { data: [1,2,3]});
expect(tableParams.settings().filterOptions.filterDelay).toBe(0);
});

it('should not set filterDelay when working with synchronous data (empty dataset)', function(){
// given
var tableParams = new NgTableParams({}, { data: []});
expect(tableParams.settings().filterOptions.filterDelay).toBe(0);
});

it('changing settings().data should reset page to 1', function(){
// given
var tableParams = createNgTableParams({ count: 1, page: 2 }, { data: [1,2,3]});
tableParams.reload();
scope.$digest();
expect(tableParams.page()).toBe(2); // checking assumptions
it('should set filterDelay when not certain working with synchronous data', function(){
// given
var tableParams = new NgTableParams({}, { data: [1,2], getData: function(){
// am I sync or async?
}});
expect(tableParams.settings().filterOptions.filterDelay).toBe(750);
});

// when
tableParams.settings({ data: [1,2,3, 4]});
it('should set filterDelay when data exceeds filterDelayThreshold', function(){
// given
var tableParams = new NgTableParams({}, { filterOptions: { filterDelayThreshold: 5 }, data: [,2,3,4,5,6] });
expect(tableParams.settings().filterOptions.filterDelay).toBe(750);
});

// then
expect(tableParams.page()).toBe(1);
it('should allow filterDelay to be set explicitly', function(){
// given
var tableParams = new NgTableParams({}, { filterOptions: { filterDelay: 100}, data: [1,2] });
expect(tableParams.settings().filterOptions.filterDelay).toBe(100);
});
});

describe('reload', function(){
Expand Down

0 comments on commit 8010e07

Please sign in to comment.