Angular: cdkVirtualFor not rendering new items

Will Luce picture Will Luce · Mar 27, 2019 · Viewed 8.7k times · Source

I'm building a vertically scrolling calendar. I'm getting the initial days to load, but when new days are added to the list, they aren't being rendered.

<cdk-virtual-scroll-viewport
  class="demo-viewport"
  [itemSize]="100"
  (onContentScrolled)="handleScrollChange($event)"
>
  <calendar-day
    *cdkVirtualFor="let day of days; trackBy: trackByFn"
    [day]="day"
  ></calendar-day>
</cdk-virtual-scroll-viewport>
<button (click)="goToToday()">go</button>

I have a service with a BehaviorSubject updating the days. I know the list of days is being updated, but the change doesn't seem to be detected.

  ngOnInit() {
    this._daysService.days$.subscribe(days => {
      this.days = days;
    })
    this.watchScroll();
    this.handleScrollingUp();
    this.handleScrollingDown();
  }

For more info, the StackBlitz repo is public https://stackblitz.com/edit/material-infinite-calendar

Answer

Akber Iqbal picture Akber Iqbal · Mar 27, 2019

The *cdkVirtualFor would only be updated if you update it immutably i.e. you cannot update the array after it is initialized. We use the spread operator to get what you are looking for.

Check this very simple stackblitz... here i have used 2 methods which you can try and see:

  • addCountryOld method mutates the array by pushing an object to our array and hence the rendered view is not updated.
  • addCountryNew method uses immutability through the spread operator which results in the rendered view getting updated.

This is the code for addCountryNew:

addCountryNew(){
    let  newObj = {'name':'stack overflow country', "code":'SO'};
    this.myList = [...this.myList, newObj];
  }