diff --git a/src/browser/index.ts b/src/browser/index.ts index 08d48427..1742a0fb 100644 --- a/src/browser/index.ts +++ b/src/browser/index.ts @@ -37,4 +37,5 @@ const ngTableBrowserModule = angular.module('ngTable-browser', []) .controller('ngTableSorterRowController', NgTableSorterRowController); export * from './public-interfaces'; -export { NgTableController, NgTableFilterConfigProvider, NgTableFilterConfig, ngTableBrowserModule }; \ No newline at end of file +export { NgTableController, ngTableBrowserModule }; +export * from './ngTableFilterConfig'; \ No newline at end of file diff --git a/src/browser/ngTableDynamic.directive.ts b/src/browser/ngTableDynamic.directive.ts index 754419a0..c4800034 100644 --- a/src/browser/ngTableDynamic.directive.ts +++ b/src/browser/ngTableDynamic.directive.ts @@ -15,6 +15,10 @@ interface ScopeExtensions { $columns: ColumnDef[] } +function toArray(arr: ArrayLike) { + return Array.prototype.slice.call(arr) as T[]; +} + ngTableDynamic.$inject = []; /** @@ -31,40 +35,35 @@ ngTableDynamic.$inject = []; * * ``` */ -export function ngTableDynamic () : IDirective{ +export function ngTableDynamic(): IDirective { return { restrict: 'A', priority: 1001, scope: true, controller: 'ngTableController', - compile: function(tElement: IAugmentedJQuery) { - let row: IAugmentedJQuery; + compile: function (tElement: IAugmentedJQuery) { - // IE 8 fix :not(.ng-table-group) selector - ng1.forEach(tElement.find('tr'), (tr: JQuery) => { - tr = ng1.element(tr); - if (!tr.hasClass('ng-table-group') && !row) { - row = tr; - } - }); - if (!row) { + const tRows = toArray(tElement[0].getElementsByTagName('tr')); + const tRow = tRows.filter(tr => !ng1.element(tr).hasClass('ng-table-group'))[0]; + + if (!tRow) { return undefined; } - ng1.forEach(row.find('td'), (item: JQuery) => { - const el = ng1.element(item); + toArray(tRow.getElementsByTagName('td')).forEach(tCell => { + const el = ng1.element(tCell); const getAttrValue = (attr: string) => { return el.attr('x-data-' + attr) || el.attr('data-' + attr) || el.attr(attr); }; // this used in responsive table const titleExpr = getAttrValue('title'); - if (!titleExpr){ + if (!titleExpr) { el.attr('data-title-text', '{{$columns[$index].titleAlt(this) || $columns[$index].title(this)}}'); } const showExpr = el.attr('ng-if'); - if (!showExpr){ + if (!showExpr) { el.attr('ng-if', '$columns[$index].show(this)'); } }); diff --git a/src/browser/ngTableFilterConfig.ts b/src/browser/ngTableFilterConfig.ts index cd92b8e3..367bf99a 100644 --- a/src/browser/ngTableFilterConfig.ts +++ b/src/browser/ngTableFilterConfig.ts @@ -8,7 +8,30 @@ import * as ng1 from 'angular'; import { IServiceProvider, auto } from 'angular'; -import { FilterConfigValues, FilterTemplateDef } from './public-interfaces'; +import { assignPartialDeep } from '../shared'; +import { FilterTemplateDef } from './public-interfaces'; + +/** + * Configuration values that determine the behaviour of the `ngTableFilterConfig` service + */ +export class FilterConfigValues { + /** + * The default base url to use when deriving the url for a filter template given just an alias name + */ + defaultBaseUrl = 'ng-table/filters/'; + /** + * The extension to use when deriving the url of a filter template when given just an alias name + */ + defaultExt = '.html'; + /** + * A map of alias names and their corrosponding urls. A lookup against this map will be used + * to find the url matching an alias name. + * If no match is found then a url will be derived using the following pattern `${defaultBaseUrl}${aliasName}.${defaultExt}` + */ + aliasUrls: { [name: string]: string } = {}; +} + +export type FilterConfigValuesPartial = Partial /** * The angular provider used to configure the behaviour of the `NgTableFilterConfig` service. @@ -17,11 +40,6 @@ export class NgTableFilterConfigProvider implements IServiceProvider { static $inject = ['$injector']; $get: () => NgTableFilterConfig; private config: FilterConfigValues; - private defaultConfig: FilterConfigValues = { - defaultBaseUrl: 'ng-table/filters/', - defaultExt: '.html', - aliasUrls: {} - }; constructor($injector: auto.IInjectorService) { this.$get = () => { return $injector.instantiate(NgTableFilterConfig, { config: ng1.copy(this.config) }); @@ -34,16 +52,14 @@ export class NgTableFilterConfigProvider implements IServiceProvider { * Reset back to factory defaults the config values that `NgTableFilterConfig` service will use */ resetConfigs() { - this.config = this.defaultConfig; + this.config = new FilterConfigValues(); } /** * Set the config values used by `NgTableFilterConfig` service */ - setConfig(customConfig: FilterConfigValues) { - const mergeConfig = ng1.extend({}, this.config, customConfig); - mergeConfig.aliasUrls = ng1.extend({}, this.config.aliasUrls, customConfig.aliasUrls); - this.config = mergeConfig; + setConfig(customConfig: FilterConfigValuesPartial) { + this.config = assignPartialDeep(ng1.copy(this.config), customConfig); } } diff --git a/src/browser/public-interfaces.ts b/src/browser/public-interfaces.ts index b38702e1..49671999 100644 --- a/src/browser/public-interfaces.ts +++ b/src/browser/public-interfaces.ts @@ -157,27 +157,6 @@ export interface DynamicTableColDef { titleAlt?: DynamicTableColField; } -/** - * Configuration values that determine the behaviour of the `ngTableFilterConfig` service - */ -export interface FilterConfigValues { - /** - * The default base url to use when deriving the url for a filter template given just an alias name - * Defaults to 'ng-table/filters/' - */ - defaultBaseUrl?: string; - /** - * The extension to use when deriving the url of a filter template when given just an alias name - */ - defaultExt?: string; - /** - * A map of alias names and their corrosponding urls. A lookup against this map will be used - * to find the url matching an alias name. - * If no match is found then a url will be derived using the following pattern `${defaultBaseUrl}${aliasName}.${defaultExt}` - */ - aliasUrls?: { [name: string]: string }; -} - /** * A key value-pair map where the key is the name of a field in a data row and the value is the definition * for the template used to render a filter cell in the header of a html table. diff --git a/test/specs/filters.spec.ts b/test/specs/filters.spec.ts index 5c248e82..7bf49681 100644 --- a/test/specs/filters.spec.ts +++ b/test/specs/filters.spec.ts @@ -1,5 +1,6 @@ -import { NgTableFilterConfig, NgTableFilterConfigProvider, ngTableBrowserModule } from '../../src/browser'; import * as ng1 from 'angular'; +import * as _ from 'lodash'; +import { NgTableFilterConfig, NgTableFilterConfigProvider, FilterConfigValues, ngTableBrowserModule } from '../../src/browser'; describe('ngTableFilterConfig', () => { let ngTableFilterConfig: NgTableFilterConfig, @@ -19,8 +20,24 @@ describe('ngTableFilterConfig', () => { })); + it('should return defaults', () => { + ngTableFilterConfig = ngTableFilterConfigProvider.$get(); + + expect(ngTableFilterConfig.config).toEqualPlainObject({ + defaultBaseUrl: 'ng-table/filters/', + defaultExt: '.html', + aliasUrls: {} + }); + }) + + describe('setConfig', () => { + let allSettings: FilterConfigValues + beforeEach(() => { + allSettings = new FilterConfigValues(); + }); + it('should set aliasUrls supplied', () => { ngTableFilterConfigProvider.setConfig({ @@ -49,6 +66,32 @@ describe('ngTableFilterConfig', () => { expect(ngTableFilterConfig.config.aliasUrls['text']).toBe('custom/url/text.html'); expect(ngTableFilterConfig.config.aliasUrls['number']).toBe('custom/url/custom-number.html'); }); + + it('undefined values in new settings should be ignored', () => { + const newSettings = _.mapValues(allSettings, _.constant(undefined)); + // when + ngTableFilterConfigProvider.setConfig(newSettings); + // then + ngTableFilterConfig = ngTableFilterConfigProvider.$get(); + expect(ngTableFilterConfig.config).toEqualPlainObject(allSettings); + }); + + it('undefined nested values in new settings should be ignored', () => { + ngTableFilterConfigProvider.setConfig({ + aliasUrls: { + 'text': 'custom/url/text.html' + } + }); + + ngTableFilterConfigProvider.setConfig({ + aliasUrls: { + 'text': undefined + } + }); + + ngTableFilterConfig = ngTableFilterConfigProvider.$get(); + expect(ngTableFilterConfig.config.aliasUrls['text']).toBe('custom/url/text.html'); + }); }); describe('getTemplateUrl', () => {