angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.32k stars 6.73k forks source link

Cdk virtual scroll not updating view on array sorting #13854

Closed RavindraGp closed 5 years ago

RavindraGp commented 5 years ago

Bug, feature request, or proposal:

cdkVirtualFor is not updating the view if array is sorted https://stackblitz.com/edit/angular-iv3ajn?embed=1 In the above example after sorting view in cdk virtual scroll is not updated where ngFor updates the view. But the same works in case of observable as given in the demo https://material2-dev.firebaseapp.com/virtual-scroll

What is the expected behavior?

Expect the view to be updated when the array is reordered.

What is the current behavior?

View is not updated when the array is sorted.

What are the steps to reproduce?

https://stackblitz.com/edit/angular-iv3ajn?embed=1

What is the use-case or motivation for changing an existing behavior?

I have a grid implementation where parent passes the array of items to child. Child component handles sorting and resizing etc. Using virtual scroll because the data can be huge. So on sorting data in child and parent component is updated but view is not getting updated.

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Material:7.0.1 Angular 6.1.10 TypeScript 3.1.1

Is there anything else we should know?

djleonskennedy commented 5 years ago

@RavindraGp Hello, you need to learn how angular works ;)

use immutable data (from your example)

sort() {
     this.items = [...this.items.sort((a, b) => a.num - b.num)]
}

and all gonna work

RavindraGp commented 5 years ago

@djleonskennedy Without using spread syntax the solution won't work. Why so ?

MurhafSousli commented 5 years ago

@RavindraGp Because angular does not detect the change until the variable value gets a new value, changing a sub value or an item in an array is not a new value.. there are tons of articles about immutability on the internet

RavindraGp commented 5 years ago

Thanks @MurhafSousli I think I have to read out more.

jrood commented 5 years ago

@RavindraGp You're on to something. There is something funky with the sorting on the cdk virtual scroll. @djleonskennedy is correct that using immutable data is necessary when using a regular array, but that should not have been an issue in your example that uses an observable. I'm seeing sorting issues even while using the spread and/or an observable. Even as I am scrolling I'm seeing things get reordered, even with template caching turned off. I'm not sure if I'll have a chance to create a stackblitz example today, but I hope to soon.

HelloClyde commented 5 years ago

When i update the item in list(not add item,just update),cdk virtual scroll not updating view too. Finially,I try this:

@ViewChild(CdkVirtualScrollViewport, {static: false}) viewport: CdkVirtualScrollViewport;

this.viewport.setRenderedRange({start: 0, end: this.viewport.getRenderedRange().end + 1});
this.viewport.checkViewportSize();

It solves my problem

Ahmdrza commented 5 years ago

@HelloClyde Where did you added given code?

HelloClyde commented 5 years ago

@HelloClyde Where did you added given code?

@Ahmdrza here is example:

@Component({
  selector: 'app-main-search',
  templateUrl: './main-search.component.html',
  styleUrls: ['./main-search.component.css'],
  changeDetection: ChangeDetectionStrategy.Default
})
export class MainSearchComponent implements OnInit {
  @ViewChild(CdkVirtualScrollViewport, {static: false}) viewport: CdkVirtualScrollViewport;

  updateList(page: number) {
    this.http.post<any>(`/api/some-path/`, {
      page
    }).subscribe(data => {
      if (page === 0) {
        // update list when first request
        this.items = this.searchResult.items;
        // assing a new list didn't works sometimes when initialization.so i try to reset renderedRange,it worked!
        this.viewport.setRenderedRange({start: 0, end: this.viewport.getRenderedRange().end + 1});
        this.viewport.checkViewportSize();
      } else {
        // update part list when append
        this.items.splice(page * this.pageSize, this.pageSize, ...data.items);
        // cdkVirtualScrollViewport re-render when assign a new list
        this.items = [...this.searchResult.items];
      }
    });
  }
}
angular-automatic-lock-bot[bot] commented 4 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.