fix(common): throw an error if trackBy is not a function (#13420)
* fix(common): throw an error if trackBy is not a function Closes #13388 * refactor(platform-browser): disable no-console rule in DomAdapter
This commit is contained in:
parent
383adc9ad9
commit
fcd116fdc0
|
@ -89,9 +89,18 @@ export class NgForRow {
|
||||||
@Directive({selector: '[ngFor][ngForOf]'})
|
@Directive({selector: '[ngFor][ngForOf]'})
|
||||||
export class NgFor implements DoCheck, OnChanges {
|
export class NgFor implements DoCheck, OnChanges {
|
||||||
@Input() ngForOf: any;
|
@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 _differ: IterableDiffer = null;
|
||||||
|
private _trackByFn: TrackByFn;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _viewContainer: ViewContainerRef, private _template: TemplateRef<NgForRow>,
|
private _viewContainer: ViewContainerRef, private _template: TemplateRef<NgForRow>,
|
||||||
|
@ -119,7 +128,7 @@ export class NgFor implements DoCheck, OnChanges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoCheck() {
|
ngDoCheck(): void {
|
||||||
if (this._differ) {
|
if (this._differ) {
|
||||||
const changes = this._differ.diff(this.ngForOf);
|
const changes = this._differ.diff(this.ngForOf);
|
||||||
if (changes) this._applyChanges(changes);
|
if (changes) this._applyChanges(changes);
|
||||||
|
|
|
@ -294,6 +294,16 @@ export function main() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('track by', () => {
|
describe('track by', () => {
|
||||||
|
it('should throw if trackBy is not a function', async(() => {
|
||||||
|
const template =
|
||||||
|
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="item?.id"></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(() => {
|
it('should set the context to the component instance', async(() => {
|
||||||
const template =
|
const template =
|
||||||
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackByContext.bind(this)"></template>`;
|
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackByContext.bind(this)"></template>`;
|
||||||
|
|
|
@ -67,7 +67,7 @@ const _chromeNumKeyPadMap = {
|
||||||
* @security Tread carefully! Interacting with the DOM directly is dangerous and
|
* @security Tread carefully! Interacting with the DOM directly is dangerous and
|
||||||
* can introduce XSS risks.
|
* can introduce XSS risks.
|
||||||
*/
|
*/
|
||||||
/* tslint:disable:requireParameterType */
|
/* tslint:disable:requireParameterType no-console */
|
||||||
export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||||
parse(templateHtml: string) { throw new Error('parse not implemented'); }
|
parse(templateHtml: string) { throw new Error('parse not implemented'); }
|
||||||
static makeCurrent() { setRootDomAdapter(new BrowserDomAdapter()); }
|
static makeCurrent() { setRootDomAdapter(new BrowserDomAdapter()); }
|
||||||
|
@ -90,7 +90,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||||
|
|
||||||
log(error: string): void {
|
log(error: string): void {
|
||||||
if (window.console) {
|
if (window.console) {
|
||||||
// tslint:disable-next-line:no-console
|
|
||||||
window.console.log && window.console.log(error);
|
window.console.log && window.console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue