Reputation: 1295
You can see my Plunk here. In this very easy example I am passing a function
_ => {
console.log(number);
}
to a child component with the @Input property. My parent component looks like that:
@Component({
selector: 'my-app',
template: `
<child [func]="getFunction(3)">
</child>
<button type="button" (click)="startChangeDetection()">
Start change detection
</button>
`,
directives : [Child],
styles:[`
.titles {
color:#0099FF
}
.child-style {
background-color:#00ffff
}
` ],
})
export class CarComponent {
startChangeDetection()
{
}
getFunction(number)
{
return _ => {
console.log(number);
}
}
}
The button does nothing else than trigger another round of change detection (there is no implementation in the callback function. However, my change detection always recognizes my input as a change, nevertheless it never changes. This is my child component:
@Component({
selector: 'child',
template: `
<h2>Child Component</h2>
`,
inputs: ['func']
})
export class Child {
private func;
ngOnChanges(changes)
{
console.log(changes.func.previousValue.toString());
console.log(changes.func.currentValue.toString());
}
}
You can see, that in ngOnChanges I log my function to the console. But the logged value (obviously) does never change, so the output is always:
function (_) {
console.log(number);
}
function (_) {
console.log(number);
}
Why the heck does Angular even call ngOnChanges? And why does it think there is any change?
Upvotes: 1
Views: 2761
Reputation: 4787
I don't see anything abnormal there. The change detection is getting called twice.
First time because child component is rendered inside car component. The component tree is changed.
Second time because the function getFunction is getting called when you are passing it as getFunction(3)
to the input. Thats equivalent to change in input value and hence triggering change detection cycle.
Upvotes: 1
Reputation: 657356
This method returns a different function instance every time getFunction
is called.
getFunction(number)
{
return _ => {
console.log(number);
}
}
because of <child [func]="getFunction(3)">
, getFunction
is called every time change detection is run.
Binding to functions is usually not the best idea. If you move out the function creation this way, the same function instance is returned every time and Angular change detection won't recognize it as change:
myCallback = _ => this.myCallBack(number) {
console.log(number);
}
getFunction(number)
{
return this.myCallback;
}
Upvotes: 3