简体   繁体   中英

ngFor not re-rendering components when array changes

@Component({
  selector: 'app-comment-section',
  templateUrl: './comment-section.component.html',
  styleUrls: ['./comment-section.component.css']
})
export class CommentSectionComponent implements OnInit, OnDestroy {

  @Input()
  private commentable: Commentable;
  private commentRoom;
  private comments: Comment[] = [];
  private onNew: Subscription;
  private onDelete: Subscription;

  constructor(private service: CommentingService, private http: HttpClient) { }

  ngOnInit() {
    this.commentRoom = this.service.joinCommentsRoom(this.commentable.uuid);

    this.http.get<CommentsResponse>(this.commentable.url).subscribe(res => {
      this.comments = res.comments.rows;
    });

    this.onNew = this.commentRoom.newComment$.subscribe((comment) => {
      this.comments.push(comment);
    })

    this.onDelete = this.commentRoom.deletedComment$.subscribe((uuid) => {
      console.log('Comment deleted...')
      this.comments = this.comments.filter(comment => {
        return comment.uuid != uuid;
      });
    })

  }

  ngOnDestroy() {
    this.onNew.unsubscribe();
    this.onDelete.unsubscribe();
    this.commentRoom.reconnect.unsubscribe();
  }

}

I have a comment section, that is using a commenting service to get observables that emit new and deleted comments. Everything seems to work, except that the view doesn't re-render when this.comments is updated as a comment is created or deleted. I can see that the values are emitted with the console.log().

This is what the ngFor looks like in the view:

<app-comment class="comment" *ngFor="let entity of comments" [entity]="entity"></app-comment>

Is there something I'm doing wrong that is causing the view to not update when the array changes?

Kind regards, Axel

Try separating the ngFor from the component you are attempting to iterate through.

<div *ngFor="let entity of comments">
  <app-comment class="comment"  [entity]="entity"></app-comment>
</div>

Sometimes, angular's onchanges hook does not register updates in cases where the child components are not directly visible

The NgForOf directive tracks by the default value, the value can still be the same even if the subvalues are changing: an [Object] is [Object] even after changing some nested values.

You can create a custom tracking function to specify what should be used to track the values :

<app-comment class="comment" *ngFor="let entity of comments; trackBy: trackByFn" 
 [entity]="entity">
</app-comment>

The function implementation must return what makes the entity unique :

trackByFn(index, entity) {
  return entity.id;
}

There is a running example in the angular.io documentation .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM