Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular modal data not refreshing after data change

Tags:

angular

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.

like image 640
KingKongFrog Avatar asked Dec 08 '22 10:12

KingKongFrog


2 Answers

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

like image 163
Vinay Avatar answered Jan 04 '23 23:01

Vinay


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

like image 35
David Avatar answered Jan 04 '23 22:01

David