Reputation: 391
Here I'm trying to study how change detection work. having array(children) in parent component and in children using change detection OnPush
. Trying to change the array by splice or push is still affecting the child component template. How come this works, even though the reference of the @Input
does not change?
my parent component.ts
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, AfterViewInit {
children = [1,2,3,4,5,6,7,8,9]
emit(j) {
this.children.splice(j, 1);
}
}
parent html
<div>
<app-multi [input]="children" (output)="emit($event)"></app-multi>
</div>
my child component.ts
@Component({
selector: 'app-multi',
templateUrl: './multi.component.html',
styleUrls: ['./multi.component.css'],
changeDetection:ChangeDetectionStrategy.OnPush
})
export class MultiComponent implements OnInit,OnChanges,DoCheck,AfterViewInit{
@Input('input') ele = [];
data = [];
@Output('output') outputEmi = new EventEmitter();
ngOnInit() {
this.data = this.ele;
}
clicks(value){
this.outputEmi.emit(value);
}
}
child html
{{name.name}}
<table>
<tbody>
<tr>
<td *ngFor="let head of data; let i = index;">
<span>{{head}}</span>
<button class="delete" (click)="clicks(i)">x</button>
</td>
</tr>
</tbody>
</table>
Upvotes: 3
Views: 4660
Reputation: 71891
To my understanding, your question is that you are wondering why change detection works, even though the reference of the @Input
doesn't change?
With the change detection strategy set to OnPush
, the child component checks its template bindings only for a couple reasons:
@Input()
value has changed@Output
In your case the second and last point happened, because of this the *ngFor
inside your child template runs again, and realizes there is an extra addition to the array from the input.
Bottom line, so even though the reference of the array stays the same, and the @Input()
does not change reference wise, there is still a change detection triggered, because the child component receives a binded (click)
and emits an @Output
.
If you were to update your code, and not use the @Output()
, the change detection will still work, because an event was binded to the template:
clicks(value){
this.input.splice(value, 1);
}
Upvotes: 8
Reputation: 1631
in order to trigger change detection, when it's OnPush you have to change the reference, so if you make splice
it will not change reference it will just update the existing array, so I encourage you to do filter
method instead of splice
, but if you have to use splice than remember to renew the reference like this
this.children.splice(i,j);
this.children = [...this.children]
Upvotes: 0