Использование ngx-virtual-scroller с разделами элементов

Я хочу использовать ngx-virtual-scroller для разделов элементов.

<virtual-scroller #scroll [items]="???">
    <div *ngFor="let group of groups;">    
       <div class="title">
            <span>{{group.name}}</span>
       </div>

       <my-item *ngFor="let item of group.items">
       </my-item>
     </div>
</virtual-scroller>

Что я должен поместить в элементы виртуального свитка ngx-virtual-scroller?

Мне нужно иметь заголовок для группы элементов .. каждый элемент принадлежит к группе.

т.е. заголовок должен быть в отдельной строке, а высота элемента больше, чем высота заголовка.

Отредактировано:

Я забыл упомянуть, что количество групп является динамическим, а также количество элементов в каждой группе динамично. Кроме того, количество элементов в группе может быть очень большим, поэтому я не хочу, чтобы элементы прокрутки были группами, потому что, если группа очень большая, я не хочу загружать ее все. в ДОМ.


person RoG    schedule 10.02.2020    source источник


Ответы (1)


Я знаю, что ваш вопрос касается ngx-virtual-scroller, но у меня есть решение для ngx-ui- scroll, что может быть полезно для вас или тех, кто занимается группировкой наборов данных. Большая часть логики кажется независимой от реализации / api скроллера, но позвольте мне подумать, что я делаю это для ngx-ui-scroll.

В этом случае нам нужно рассматривать groups как источник данных, который должен реализовывать метод get в соответствии с документами ngx-ui-scroll. Как следующие

groups = new Datasource({
  get: (index, count, success) =>
    success(this.getItems(index, count)
  )
})

Я не знаю структуры ваших данных, и это не должно иметь значения, потому что мы обсуждаем подход. Единственное, что нам нужно учитывать, - это согласованность между источником данных и шаблоном. Представьте, что у нас уже есть набор данных плоских элементов фиксированной длины.

data = [];
MIN = 1;
MAX = 200;

constructor() {
  for (let i = this.MIN; i <= this.MAX; i++) {
    this.data.push({ id: i, text: 'item #' + i });
  }
}

И вы хотите их сгруппировать. Какие у вас могут быть группы? Это зависит от того, сколько предметов вы хотите быть в одной группе.

this.ITEMS_PER_GROUP = 3;
this.groupsCount = Math.ceil((this.MAX - this.MIN) / this.ITEMS_PER_GROUP);

Затем, возвращаясь к реализации getItems, я бы предложил разделить процедуру получения элементов на 2 метода. Получение групп (по счетчику индекса из-за ngx-ui-scroll api):

getItems(index: number, count: number) {
  const data = [];
  const start = Math.max(1, index);
  const end = Math.min(this.groupsCount, index + count - 1);
  if (start <= end) {
    for (let i = start; i <= end; i++) {
      const group = this.getGroup(i);
      if (group) {
        data.push(group);
      }
    }
  }
  return data;
}

и получение одной группы по индексу:

getGroup(index: number) {
  let result = null;
  const data = [];
  const start = this.MIN + (index - 1) * this.ITEMS_PER_GROUP;
  const end = start + this.ITEMS_PER_GROUP - 1;
  if (start <= end) {
    for (let i = start; i <= end; i++) {
      const item = this.data.find(item => item.id === i);
      if (item) {
        data.push(item);
      }
    }
    result = {
      title: 'Group ' + index,
      items: data
    };
  }
  return result;
}

Таким образом, вы получите источник данных, соответствующий тому, что вам нужно в слое шаблона. С ngx-ui-scroll это будет выглядеть следующим образом:

<div *uiScroll="let group of groups">
  <div>{{group.title}}</div>
  <div *ngFor="let item of group.items">
    <div class="item">{{item.text}}</div>
  </div>
</div>

Говоря о ngx-ui-scroll, все ограничения могут быть сняты, я имею в виду, что вы можете не знать границ набора данных и количества групп, но реализация будет немного другой.

Наконец, я создал демо, так как случай кажется полезным для пользователей ngx-ui-scroll

https://stackblitz.com/edit/angular-ngx-ui-scroll-1-3-4-grouping-datasource

person dhilt    schedule 11.02.2020
comment
Привет, спасибо за ответ. Забыл упомянуть, что все группы получаю из другого сервиса. Количество групп является динамическим, а количество элементов в каждой группе является динамическим, и это может быть очень большое количество элементов в группе. Вот почему я не хотел делать items = groups, и потому что, если у меня большая группа, я не хочу загружать все это в DOM. - person RoG; 12.02.2020
comment
@RoG В этом случае я бы попробовал противоположный, скажем, подход сглаживания: создать дополнительный слой, выделенный для предоставления массива элементов для скроллера, построенного из группового массива в соответствии с совокупными требованиями приложения / скроллера, ограниченного индексом плоского списка элементов , а не по групповому индексу. Заголовок группы может рассматриваться как другой элемент в потоке плоских элементов результатов. - person dhilt; 12.02.2020
comment
Да, это то, что я хотел сделать, но я хотел знать, есть ли другое решение, о котором я не думаю. Проблема в этом решении заключается в том, что заголовок должен быть в отдельной строке, но элементы могут быть 5 в строке или более / менее в зависимости от ширины экрана ... это должна быть прокрутка с несколькими столбцами, а также неравные дочерние элементы размеры (размер заголовка отличается от размера элемента). - person RoG; 13.02.2020
comment
@RoG Требования слишком специфичны, это кажется возможным, но я боюсь, что ни одно из готовых решений не позволит вам сделать это из коробки, поэтому вам придется реализовать это самостоятельно - person dhilt; 13.02.2020