I've following code. Parent is sending some data to the child component using @Input
directive:
Parent HTML
<div>
<my-timeline
[data]="data">
</my-timeline>
</div>
In Parent TS there is a service that provides data to data
Parent TS
data=[];
...
this.service.getData().subscribe(res => {
res.map(item=>{
this.data.push({
...
});
})
})
And the child is receiving it as
Child TS
@Input data;
eventArray=[];
ngOnInit() {
console.log("called"); // called only for the first time
createTimeline(data[0].id); // called only for the first time
}
createTimeline(id) { // called only for the first time
this.eventArray.push(.....)
}
Child HTML
<p-timeline [value]="eventArray">
...
</p-timeline>
The problem is that the p-timeline
continues to show old events i.e. the events it loaded for the very first time. Because with subsequent data change from the Parent it is not causing ngOnIt in child to run. That is why createTimeline
was never called again. Please pitch in.
CodePudding user response:
In order to detect changes to an @Input property you can implement one of the following:
OnChanges lifecycle hook -
First, lets explain what is
OnChanges
hook?From Angular.io:
OnChanges is a lifecycle hook that is called when any data-bound property of a directive changes. Define an ngOnChanges() method to handle the changes.
Lets implement the OnChanges lifecycle hook, something like this:
@Component({...})
export class SelectedPlayerComponent implements OnChanges {
@Input() data;
ngOnChanges(changes: SimpleChanges) {
if(changes.data)
{
this.createTimeline(changes.data.currentValue[0].id);//the new value that's changed
}
}
}
- Setter - Implement the @Input() property as getter and setter, something like this:
private _data: any;
@Input()
set data(value: any) {
this._data= value;
if(this._data)
this.createTimeline(this._data[0].id)
}
get data(): any{
return this._data;
}
Thanks for Todd Motto good article about detect input changes in angular
CodePudding user response:
Use ChangeDetectionStrategy.Default
on all your components or use immutable data approach e.g
this.data = [...this.data, {//item}];
Can read up on it in the docs, along with how Angular ngOnInit
works