Skip to content

Commit 0966428

Browse files
committed
feat(ngTableFilterConfig): nested options never undefined
This is part of supporting typescript strictNullChecks compiler option. BREAKING CHANGES `NgTableFilterConfigProvider.setConfig`: any config value supplied as undefined will now be ignored Instead of `undefined` you will need to supply a suitable value as described below: * `aliasUrls` - an empty object to reset configuration back to using filter templates supplied by the ng-table library
1 parent 29659a9 commit 0966428

File tree

5 files changed

+87
-49
lines changed

5 files changed

+87
-49
lines changed

src/browser/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ const ngTableBrowserModule = angular.module('ngTable-browser', [])
3737
.controller('ngTableSorterRowController', NgTableSorterRowController);
3838

3939
export * from './public-interfaces';
40-
export { NgTableController, NgTableFilterConfigProvider, NgTableFilterConfig, ngTableBrowserModule };
40+
export { NgTableController, ngTableBrowserModule };
41+
export * from './ngTableFilterConfig';

src/browser/ngTableDynamic.directive.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ interface ScopeExtensions {
1515
$columns: ColumnDef[]
1616
}
1717

18+
function toArray<T>(arr: ArrayLike<T>) {
19+
return Array.prototype.slice.call(arr) as T[];
20+
}
21+
1822
ngTableDynamic.$inject = [];
1923

2024
/**
@@ -31,40 +35,35 @@ ngTableDynamic.$inject = [];
3135
* </table>
3236
* ```
3337
*/
34-
export function ngTableDynamic () : IDirective{
38+
export function ngTableDynamic(): IDirective {
3539

3640
return {
3741
restrict: 'A',
3842
priority: 1001,
3943
scope: true,
4044
controller: 'ngTableController',
41-
compile: function(tElement: IAugmentedJQuery) {
42-
let row: IAugmentedJQuery;
45+
compile: function (tElement: IAugmentedJQuery) {
4346

44-
// IE 8 fix :not(.ng-table-group) selector
45-
ng1.forEach(tElement.find('tr'), (tr: JQuery) => {
46-
tr = ng1.element(tr);
47-
if (!tr.hasClass('ng-table-group') && !row) {
48-
row = tr;
49-
}
50-
});
51-
if (!row) {
47+
const tRows = toArray(tElement[0].getElementsByTagName('tr'));
48+
const tRow = tRows.filter(tr => !ng1.element(tr).hasClass('ng-table-group'))[0];
49+
50+
if (!tRow) {
5251
return undefined;
5352
}
5453

55-
ng1.forEach(row.find('td'), (item: JQuery) => {
56-
const el = ng1.element(item);
54+
toArray(tRow.getElementsByTagName('td')).forEach(tCell => {
55+
const el = ng1.element(tCell);
5756
const getAttrValue = (attr: string) => {
5857
return el.attr('x-data-' + attr) || el.attr('data-' + attr) || el.attr(attr);
5958
};
6059

6160
// this used in responsive table
6261
const titleExpr = getAttrValue('title');
63-
if (!titleExpr){
62+
if (!titleExpr) {
6463
el.attr('data-title-text', '{{$columns[$index].titleAlt(this) || $columns[$index].title(this)}}');
6564
}
6665
const showExpr = el.attr('ng-if');
67-
if (!showExpr){
66+
if (!showExpr) {
6867
el.attr('ng-if', '$columns[$index].show(this)');
6968
}
7069
});

src/browser/ngTableFilterConfig.ts

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,30 @@
88

99
import * as ng1 from 'angular';
1010
import { IServiceProvider, auto } from 'angular';
11-
import { FilterConfigValues, FilterTemplateDef } from './public-interfaces';
11+
import { assignPartialDeep } from '../shared';
12+
import { FilterTemplateDef } from './public-interfaces';
13+
14+
/**
15+
* Configuration values that determine the behaviour of the `ngTableFilterConfig` service
16+
*/
17+
export class FilterConfigValues {
18+
/**
19+
* The default base url to use when deriving the url for a filter template given just an alias name
20+
*/
21+
defaultBaseUrl = 'ng-table/filters/';
22+
/**
23+
* The extension to use when deriving the url of a filter template when given just an alias name
24+
*/
25+
defaultExt = '.html';
26+
/**
27+
* A map of alias names and their corrosponding urls. A lookup against this map will be used
28+
* to find the url matching an alias name.
29+
* If no match is found then a url will be derived using the following pattern `${defaultBaseUrl}${aliasName}.${defaultExt}`
30+
*/
31+
aliasUrls: { [name: string]: string } = {};
32+
}
33+
34+
export type FilterConfigValuesPartial = Partial<FilterConfigValues>
1235

1336
/**
1437
* The angular provider used to configure the behaviour of the `NgTableFilterConfig` service.
@@ -17,11 +40,6 @@ export class NgTableFilterConfigProvider implements IServiceProvider {
1740
static $inject = ['$injector'];
1841
$get: () => NgTableFilterConfig;
1942
private config: FilterConfigValues;
20-
private defaultConfig: FilterConfigValues = {
21-
defaultBaseUrl: 'ng-table/filters/',
22-
defaultExt: '.html',
23-
aliasUrls: {}
24-
};
2543
constructor($injector: auto.IInjectorService) {
2644
this.$get = () => {
2745
return $injector.instantiate<NgTableFilterConfig>(NgTableFilterConfig, { config: ng1.copy(this.config) });
@@ -34,16 +52,14 @@ export class NgTableFilterConfigProvider implements IServiceProvider {
3452
* Reset back to factory defaults the config values that `NgTableFilterConfig` service will use
3553
*/
3654
resetConfigs() {
37-
this.config = this.defaultConfig;
55+
this.config = new FilterConfigValues();
3856
}
3957

4058
/**
4159
* Set the config values used by `NgTableFilterConfig` service
4260
*/
43-
setConfig(customConfig: FilterConfigValues) {
44-
const mergeConfig = ng1.extend({}, this.config, customConfig);
45-
mergeConfig.aliasUrls = ng1.extend({}, this.config.aliasUrls, customConfig.aliasUrls);
46-
this.config = mergeConfig;
61+
setConfig(customConfig: FilterConfigValuesPartial) {
62+
this.config = assignPartialDeep(ng1.copy(this.config), customConfig);
4763
}
4864
}
4965

src/browser/public-interfaces.ts

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -157,27 +157,6 @@ export interface DynamicTableColDef {
157157
titleAlt?: DynamicTableColField<string>;
158158
}
159159

160-
/**
161-
* Configuration values that determine the behaviour of the `ngTableFilterConfig` service
162-
*/
163-
export interface FilterConfigValues {
164-
/**
165-
* The default base url to use when deriving the url for a filter template given just an alias name
166-
* Defaults to 'ng-table/filters/'
167-
*/
168-
defaultBaseUrl?: string;
169-
/**
170-
* The extension to use when deriving the url of a filter template when given just an alias name
171-
*/
172-
defaultExt?: string;
173-
/**
174-
* A map of alias names and their corrosponding urls. A lookup against this map will be used
175-
* to find the url matching an alias name.
176-
* If no match is found then a url will be derived using the following pattern `${defaultBaseUrl}${aliasName}.${defaultExt}`
177-
*/
178-
aliasUrls?: { [name: string]: string };
179-
}
180-
181160
/**
182161
* A key value-pair map where the key is the name of a field in a data row and the value is the definition
183162
* for the template used to render a filter cell in the header of a html table.

test/specs/filters.spec.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { NgTableFilterConfig, NgTableFilterConfigProvider, ngTableBrowserModule } from '../../src/browser';
21
import * as ng1 from 'angular';
2+
import * as _ from 'lodash';
3+
import { NgTableFilterConfig, NgTableFilterConfigProvider, FilterConfigValues, ngTableBrowserModule } from '../../src/browser';
34

45
describe('ngTableFilterConfig', () => {
56
let ngTableFilterConfig: NgTableFilterConfig,
@@ -19,8 +20,24 @@ describe('ngTableFilterConfig', () => {
1920
}));
2021

2122

23+
it('should return defaults', () => {
24+
ngTableFilterConfig = ngTableFilterConfigProvider.$get();
25+
26+
expect(ngTableFilterConfig.config).toEqualPlainObject({
27+
defaultBaseUrl: 'ng-table/filters/',
28+
defaultExt: '.html',
29+
aliasUrls: {}
30+
});
31+
})
32+
33+
2234
describe('setConfig', () => {
2335

36+
let allSettings: FilterConfigValues
37+
beforeEach(() => {
38+
allSettings = new FilterConfigValues();
39+
});
40+
2441
it('should set aliasUrls supplied', () => {
2542

2643
ngTableFilterConfigProvider.setConfig({
@@ -49,6 +66,32 @@ describe('ngTableFilterConfig', () => {
4966
expect(ngTableFilterConfig.config.aliasUrls['text']).toBe('custom/url/text.html');
5067
expect(ngTableFilterConfig.config.aliasUrls['number']).toBe('custom/url/custom-number.html');
5168
});
69+
70+
it('undefined values in new settings should be ignored', () => {
71+
const newSettings = _.mapValues(allSettings, _.constant(undefined));
72+
// when
73+
ngTableFilterConfigProvider.setConfig(newSettings);
74+
// then
75+
ngTableFilterConfig = ngTableFilterConfigProvider.$get();
76+
expect(ngTableFilterConfig.config).toEqualPlainObject(allSettings);
77+
});
78+
79+
it('undefined nested values in new settings should be ignored', () => {
80+
ngTableFilterConfigProvider.setConfig({
81+
aliasUrls: {
82+
'text': 'custom/url/text.html'
83+
}
84+
});
85+
86+
ngTableFilterConfigProvider.setConfig({
87+
aliasUrls: {
88+
'text': undefined
89+
}
90+
});
91+
92+
ngTableFilterConfig = ngTableFilterConfigProvider.$get();
93+
expect(ngTableFilterConfig.config.aliasUrls['text']).toBe('custom/url/text.html');
94+
});
5295
});
5396

5497
describe('getTemplateUrl', () => {

0 commit comments

Comments
 (0)