In Angular 1 we avoided calling functions from within template expressions in excess, e.g. ng-repeat="item in vm.getFilteredItems()"
because property changes unrelated to the result of getFilteredItems
would cause the function to recompute repeatedly and unnecessarily on digests, which commonly causes performance problems at scale. Instead we bound to objects, and compute based on events (e.g. ng-repeat="item in vm.filteredItems
).
In Angular 2, the dirty checking process has been optimized but functions called in component templates will still be called when any properties at the component level change, regardless of whether the function is dependent on those properties. I expect this could lead to the same performance issues if used improperly.
Here is a simplified example of the differing approaches in Angular 2:
// function binding in template
@Component({
selector: 'func',
template: `
<input [(ngModel)]="searchTerm" placeholder="searchTerm" />
<div *ngFor="let name of filteredNames(searchTerm)">{{name}}</div>
`
})
export class FuncComponent {
@Input() names:string[];
filteredNames(searchTerm) {
if (!searchTerm) return this.names;
let filteredNames = [];
return this.names.filter((name) => {
return name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1;
});
}
}
-
// no function binding
@Component({
selector: 'nofunc',
template: `
<input [(ngModel)]="searchTerm" (ngModelChange)="search($event)" placeholder="searchTerm" />
<div *ngFor="let name of filteredNames">{{name}}</div>
`
})
export class NoFuncComponent implements OnInit {
@Input() names:string[];
searchTerm: string;
ngOnInit() {
this.search(this.searchTerm);
}
search() {
if (!this.searchTerm) {
this.filteredNames = this.names;
return;
}
this.filteredNames = this.names.filter((name) => {
return name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1;
});
}
}
http://plnkr.co/edit/AAFknlJgso3D8F1w3QC1?p=preview
Is this still a concern in Angular 2? Which approach is preferred, and why? Thanks!
There are two ways to pass data into a component, with 'property binding' and 'event binding'.
Two-way data binding in Angular will help users to exchange data from the component to view and from view to the component. It will help users to establish communication bi-directionally. Two-way data binding can be achieved using a ngModel directive in Angular.
You can simply extend your base component and overwrite the template. This allows you to have different components with the exact same functionality, but different templates. Save this answer.
Property binding is the primary way of binding data in Angular.
You could create a pipe. Pipes (if pure
) are only called when depending values change.
@Pipe({
name: 'search',
// pure: 'false'
})
class SearchPipe {
transform(names, searchTerm) {
if (!this.searchTerm) {
this.filteredNames = names;
return;
}
return names.filter((name) => {
return name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1;
});
}
}
@Component({
selector: 'func',
pipes: [SearchPipe],
template: `
<input [(ngModel)]="searchTerm" placeholder="searchTerm" />
<div *ngFor="let name of names | search:searchTerm">{{name}}</div>
`
})
export class FuncComponent {
@Input() names:string[];
}
If the pipe needs to recognize changes in names
then pure
needs to be disabled.
If names
is replaced by a different instance instead of just members being added or removed, then pure
works fine and the pipe is only executed when names
or searchTerm
changes.
Hint
In devMode
(default) change detection runs twice and the pipe will be called twice as much as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With