diff --git a/modules/@angular/common/src/directives/ng_for.ts b/modules/@angular/common/src/directives/ng_for.ts index a48cb83c9c..ea5803ae57 100644 --- a/modules/@angular/common/src/directives/ng_for.ts +++ b/modules/@angular/common/src/directives/ng_for.ts @@ -89,9 +89,18 @@ export class NgForRow { @Directive({selector: '[ngFor][ngForOf]'}) export class NgFor implements DoCheck, OnChanges { @Input() ngForOf: any; - @Input() ngForTrackBy: TrackByFn; + @Input() + set ngForTrackBy(fn: TrackByFn) { + if (typeof fn !== 'function') { + throw new Error(`trackBy must be a function, but received ${JSON.stringify(fn)}`); + } + this._trackByFn = fn; + } + + get ngForTrackBy(): TrackByFn { return this._trackByFn; } private _differ: IterableDiffer = null; + private _trackByFn: TrackByFn; constructor( private _viewContainer: ViewContainerRef, private _template: TemplateRef, @@ -119,7 +128,7 @@ export class NgFor implements DoCheck, OnChanges { } } - ngDoCheck() { + ngDoCheck(): void { if (this._differ) { const changes = this._differ.diff(this.ngForOf); if (changes) this._applyChanges(changes); diff --git a/modules/@angular/common/test/directives/ng_for_spec.ts b/modules/@angular/common/test/directives/ng_for_spec.ts index 5930ae10cf..e9bbdd55d2 100644 --- a/modules/@angular/common/test/directives/ng_for_spec.ts +++ b/modules/@angular/common/test/directives/ng_for_spec.ts @@ -294,6 +294,16 @@ export function main() { })); describe('track by', () => { + it('should throw if trackBy is not a function', async(() => { + const template = + ``; + fixture = createTestComponent(template); + + getComponent().items = [{id: 1}, {id: 2}]; + expect(() => fixture.detectChanges()) + .toThrowError(/trackBy must be a function, but received null/); + })); + it('should set the context to the component instance', async(() => { const template = ``; diff --git a/modules/@angular/platform-browser/src/browser/browser_adapter.ts b/modules/@angular/platform-browser/src/browser/browser_adapter.ts index 68dce3b009..2ad4d606bc 100644 --- a/modules/@angular/platform-browser/src/browser/browser_adapter.ts +++ b/modules/@angular/platform-browser/src/browser/browser_adapter.ts @@ -67,7 +67,7 @@ const _chromeNumKeyPadMap = { * @security Tread carefully! Interacting with the DOM directly is dangerous and * can introduce XSS risks. */ -/* tslint:disable:requireParameterType */ +/* tslint:disable:requireParameterType no-console */ export class BrowserDomAdapter extends GenericBrowserDomAdapter { parse(templateHtml: string) { throw new Error('parse not implemented'); } static makeCurrent() { setRootDomAdapter(new BrowserDomAdapter()); } @@ -90,7 +90,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { log(error: string): void { if (window.console) { - // tslint:disable-next-line:no-console window.console.log && window.console.log(error); } }