I have data that is displayed in a modal. However, when my data is updated and parent detects this, my modal data is never updated. Am I missing something?
PARENT:
@Input() players: Players[] = [];
showPlayers() {
const modalRef = this.modalService.open(PlayersModalComponent, {
data: { players: this.players }
},
});
}
ngOnChanges(changes: SimpleChanges) {
console.log('changes', changes);
// This shows that players has changed and gone from say 2 players to 3 players after a few actions. But modal doesn't update.
}
Modal
this.players = this.modalRef.data.players;
Modal HTML
Here I just list the players and initially they are perfect. But they do not update when a new player is added and ngChanges in parent ALSO shows there is a new row.
<modal class="modal" *ngIf="players">
<div>
<div *ngFor="let player of players">
{{player.name}}
</div>
</div>
</modal>
However, if new result is added --- since I am pulsing on API from parent. The change is detected but the list of players in modals is not updated.
You can use ngFor trackBy
function to detect changes
<modal class="modal" *ngIf="players">
<div>
<div *ngFor="let player of players, trackBy: trackItem">
{{player.name}}
</div>
</div>
</modal>
and add trackItem function
trackItem(item: any): any {
return item.id;
}
item should have unique id
Normally, everything should work straight away if you were always modifying the same instance of the players
array (stackblitz demo).
So the players
@Input passed to your parent component is probably a new instance of an array each time.
Since the players
property in your player modal component is only initialised once ( this.players = this.modalRef.data.players;
); once the players
for the parent variable changes, the players
variable from the modal component is still pointing to the previous array.
To solve this, you can either pass an observable to the modal itself like explained in Andrei's answer, or you can explicitely modify the modal's players
variable when the parent's players
input changes.
You can do that either using ngOnChanges
(stackblitz demo)
parent.component.ts
ngOnChanges(changes: SimpleChanges) {
if(this.modalRef && changes.players.currentValue)
{
this.modalRef.componentInstance.players = changes.players.currentValue;
}
}
Or using a setter (stackblitz demo)
parent.component.ts
@Input() set players(players: Players[])
{
if(this.modalRef)
{
this.modalRef.componentInstance.players = players;
}
}
These examples rely on the fact that your modalRef
contains an instance of the component used in the dialog
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