Получение статической ссылки на компонент в cdk-virtual-scroller? (Ссылки переработаны)

Недавно мы перевели наши прокручиваемые списки на CDK Virtual Scroller. (Angular 7.2.12 с angular / cdk 7.3.7)

Короче говоря, похоже, что VirtualScrollViewport перерабатывает экземпляры компонентов, а не только шаблон, как предлагает документация.

Live MCVE на StackBlitz (обновлено с учетом РЕДАКТИРОВАНИЯ 1).

ИЗМЕНИТЬ 1

Коллега напомнил мне, что теперь мы используем именованные ссылки вместо ViewChildren(), например:

HelloComponent (внутри *cdkVirtualFor):

@Component({
  selector: 'hello',
  template: `<h1 [class.active]="active">Data Item {{item}} !</h1>`,
  styles: [`.active {background-color: red; color: white}`]
})
export class HelloComponent  {
  @Input() item: any;
  active: boolean = false;
  toggle = () => this.active = !this.active;
}

И реализуя это в приложении, например:

<cdk-virtual-scroll-viewport itemSize="75">
  <ng-container *cdkVirtualFor="let item of data" templateCacheSize=0>
    <hello #hi [item]="item" (click)="clickByReference(hi)"></hello>
  </ng-container>
</cdk-virtual-scroll-viewport>

// Non-essentials hidden, see StackBlitz
export class AppComponent  {
  data = Array.from(Array(100).keys())
  clickByReference = (element: any): void => element.toggle();
}

Он изменит цвет фона элемента, по которому щелкнули мышью, на красный, но при прокрутке другие (предположительно те, которые соответствуют некоторому кешированному индексу?) Уже будут красными! Активация одного из них также очистит оригинал.

может помочь, _7 но это не так.

Исходный

Прокручиваемая область содержит компоненты, на которые мы получаем ссылку с помощью @ViewChildren() и QueryList, и мы отслеживаем, какой из них мы действуем, используя индекс в *ngFor (теперь *cdkVirtualFor), например:

<cdk-virtual-scroll-viewport itemSize="75">
  <ng-container *cdkVirtualFor="let item of data; let i = index">
    <hello  #hi
            [item]="item"
            (click)="click(i)"></hello>
  </ng-container>
</cdk-virtual-scroll-viewport>

Затем со страницы мы общаемся с компонентом в списке:

export class AppComponent  {
  @ViewChildren('hi') hiRefs: QueryList<HelloComponent>;
  data = Array.from(Array(100).keys())

  click = (i: number) => this.hiRefs["_results"][i].say(`Hello as ${i}`);
}

Конечно, теперь, когда шаблон отображается в контейнере виртуальной прокрутки, только первые n отображаются в DOM. Таким образом, если вы прокрутите список вниз, помимо того, что изначально загружено, hiRefs не будет содержать ссылки на элемент с соответствующим индексом, а вместо предоставленного ["_results"][i] будет выдан ReferenceError.

Я экспериментировал с trackBy, но ничего плодотворного не вышло.

ИЗМЕНИТЬ: коллега также попытался передать именованную ссылку, что, как ни странно, имеет ту же проблему.

Обновление HelloComponent до

@Component({
  selector: 'hello',
  template: `<h1 [class.active]="active">Data Item {{item}} !</h1>`,
  styles: [`.active {background-color: red}`]
})
export class HelloComponent  {
  @Input() item: any;
  active: boolean;

  say = (something: any) => this.active = !this.active;
}

И реализуя это в приложении, например:

<hello #hi [item]="item" (click)="clickByReference(hi)"></hello>

Он изменит цвет фона элемента, по которому щелкнули мышью, на красный, но при прокрутке другие (предположительно те, которые соответствуют тому же индексу) уже будут красными, несмотря на то, что @ViewChildren() QueryList вообще не используется!

Кажется, что CDK перерабатывает ссылки на экземпляры компонентов?

Я обновил StackBlitz методом clickByReference() и переименовал предыдущий в clickByIndex().

Как правильно получить ссылку на компонент в списке, чтобы вызвать на нем методы?


person msanford    schedule 15.04.2019    source источник


Ответы (1)