Angular CDK Виртуальная прокрутка, не выделяющая сразу все столбцы в matselect, большой набор данных. - PullRequest
1 голос
/ 19 апреля 2020

У меня есть коврик в angular, как это с виртуальной прокруткой.

<mat-select [formControl]="multiSelectControl" multiple [value]="selected" (openedChange)="openChange($event)">
  <cdk-virtual-scroll-viewport itemSize="5" minBufferPx="200" maxBufferPx="400" [style.height.px]=5*48>
    <button (click)="selectAll()">Select All</button>
    <button (click)="clear()">Clear</button>
    <mat-option *cdkVirtualFor="let topping of toppingList" [value]="topping" (onSelectionChange)="onSelectionChange($event)">{{topping}}</mat-option>
  </cdk-virtual-scroll-viewport>
</mat-select>

.ts файл:

@ViewChildren(MatOption)
options: QueryList<MatOption>;

constructor(private cd: ChangeDetectorRef) {}

ngAfterViewInit(): void {
  this.options.changes.subscribe(() => {
    let needUpdate = false;

    this.options.forEach((option) => {
      const selected = this.selected.includes(option.value);
       if (selected && !option.selected) {
        option.select();
        needUpdate = true;
      } else if (!selected && option.selected) {
        option.deselect();
        needUpdate = true;
      }
    });
    if (needUpdate) {
      this.cd.detectChanges();
    }
  });
}

onSelectionChange(change): void {
  if (!change.isUserInput) {
    return;
  }

  const value = change.source.value;
  const idx = this.selected.indexOf(change.source.value);

  if (idx > -1) {
    this.selected.splice(idx, 1)
  } else {
    this.selected.push(value);
  }
}

со ссылкой stackblitz .

Если я нажимаю Выбрать все и прокручиваю быстрее, все Элемент не выбирается так, как требуется время для его выбора. Есть ли способ улучшить производительность.

1 Ответ

2 голосов
/ 19 апреля 2020

Можно было бы прослушать прокручиваемый Observable на ScrollDispatcher:

  ngAfterViewInit(): void {
    this.sd.scrolled().pipe(
      filter((scrollable) => this.cdkVirtualScrollViewPort === scrollable)
    ).subscribe(() => {
      let needUpdate = false;

      this.options.forEach((option) => {
        const selected = this.selected.includes(option.value);

        if (selected && !option.selected) {
          option.select();
          needUpdate = true;
        } else if (!selected && option.selected) {
          option.deselect();
          needUpdate = true;
        }
      });

      if (needUpdate) {
        this.cd.detectChanges();
      }
    });
  }

Вы можете потенциально отменить событие, чтобы оно не получало выстрелил слишком много. Я обновил stackblitz этим решением

stackblitz

...