Столбцы пространства строк таблицы угловых материалов на основе размера свойства массива объекта dataSource - PullRequest
0 голосов
/ 19 декабря 2018

Даже сейчас в версии 7.2 Angular Material я не могу найти примеры того, как использовать rowspan на mat-table и сохранить функциональность компонента.

Это как далеко (коротко?) Яу меня есть:

https://stackblitz.com/edit/angular-wudscb

Пример в Stackblitz выше "почти" то, что я ищу, но я не могу увидеть, как это закончить.

...
===============================================
||     ||            ||            ||  row1  ||
||  1  ||  Hydrogen  ||   1.0079   ||========||
||     ||            ||            ||  row2  ||
===============================================
||     ||            ||            ||  row1  ||
||     ||            ||            ||========||
||  2  ||   Helium   ||   4.0026   ||  row2  ||
||     ||            ||            ||========||
||     ||            ||            ||  row3  ||
===============================================
||     ||            ||            ||  row1  ||
||  3  ||  Lithium   ||   6.941    ||========||
||     ||            ||            ||  row2  ||
===============================================
...

Пример использования другого формата метаданных можно найти в:

https://stackblitz.com/edit/angular-lnahlh

После моего Stackblitz (первая ссылка) мои вопросы:

Неужели я слишком далёк от того, чтобы достигнуть этого шим / хака для набора строк?

Как зациклить строки, основываясь на длине размера строки ['описания']?

Что если бы у меня былодругое свойство массива внутри объекта?Могу ли я выполнить итерацию и сгенерировать столбцы / строки / строки со своим размером, чтобы он стал более общим?

Я пытаюсь найти общее решение для сообщества.

Ответы [ 3 ]

0 голосов
/ 24 декабря 2018

Что ж, похоже, что в таблице материалов нет документации по API, я не могу найти какой-либо хитрости, чтобы сделать это тоже, но мы можем изменить наши данные, чтобы поддержать это, согласно вашему второму примеру, мы можем преобразовать данные вновый json, и мы можем получить ожидаемый результат.

Шаг 1:

    const originalData = [
      { id: 1, name: 'Hydrogen', weight: 1.0079, descriptions: ['row1', 'row2'] },
      { id: 2, name: 'Helium', weight: 4.0026, descriptions: ['row1', 'row2', 'row3'] },
      { id: 3, name: 'Lithium', weight: 6.941, descriptions: ['row1', 'row2'] },
      { id: 4, name: 'Beryllium', weight: 9.0122, descriptions: ['row1', 'row2', 'row3'] },
      { id: 5, name: 'Boron', weight: 10.811, descriptions: ['row1'] },
      { id: 6, name: 'Carbon', weight: 12.0107, descriptions: ['row1', 'row2', 'row3'] },
      { id: 7, name: 'Nitrogen', weight: 14.0067, descriptions: ['row1'] },
      { id: 8, name: 'Oxygen', weight: 15.9994, descriptions: ['row1'] },
      { id: 9, name: 'Fluorine', weight: 18.9984, descriptions: ['row1', 'row2', 'row3'] },
      { id: 10, name: 'Neon', weight: 20.1797, descriptions: ['row1', 'row2', 'row3'] },
    ]; //original data

    const DATA = originalData.reduce((current, next) => {
      next.descriptions.forEach(b => {
        current.push({ id: next.id, name: next.name, weight: next.weight, descriptions: b })
      });
      return current;
    }, []);//iterating over each one and adding as the description 
    console.log(DATA)

    const ELEMENT_DATA: PeriodicElement[] = DATA; //adding data to the element data

Шаг 2

Это будет так же, как и ваша вторая ссылка на стек.

 getRowSpan(col, index) {    
    return this.spans[index] && this.spans[index][col];
  }

Шаг 3

в соответствии с вашей второй ссылкой

  constructor() {
    this.cacheSpan('Priority', d => d.id);
    this.cacheSpan('Name', d => d.name);
    this.cacheSpan('Weight', d => d.weight);
  }

  /**
   * Evaluated and store an evaluation of the rowspan for each row.
   * The key determines the column it affects, and the accessor determines the
   * value that should be checked for spanning.
   */
  cacheSpan(key, accessor) {
    for (let i = 0; i < DATA.length;) {
      let currentValue = accessor(DATA[i]);
      let count = 1;

      // Iterate through the remaining rows to see how many match
      // the current value as retrieved through the accessor.
      for (let j = i + 1; j < DATA.length; j++) {
        if (currentValue != accessor(DATA[j])) {
          break;
        }

        count++;
      }

      if (!this.spans[i]) {
        this.spans[i] = {};
      }

      // Store the number of similar values that were found (the span)
      // and skip i to the next unique row.
      this.spans[i][key] = count;
      i += count;
    }
  }

Шаг 4

Использование индекса для перехода к диапазону строк и скрытиестроки, где это не нужно

    <ng-container matColumnDef="id">
        <th mat-header-cell *matHeaderCellDef> Priority </th>
        <td mat-cell *matCellDef="let data;let i = dataIndex" [attr.rowspan]="getRowSpan('Priority',i)" [style.display]="getRowSpan('Priority', i) ? '' : 'none'">
         {{ data.id }} </td>
    </ng-container>

    <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef> Name </th>
        <td mat-cell *matCellDef="let data;let i = dataIndex" [attr.rowspan]="getRowSpan('Name',i)" [style.display]="getRowSpan('Name', i) ? '' : 'none'">
         {{ data.name }} </td>
    </ng-container>

    <ng-container matColumnDef="weight">
        <th mat-header-cell *matHeaderCellDef> Weight </th>
        <td mat-cell *matCellDef="let data;let i = dataIndex" [attr.rowspan]="getRowSpan('Weight',i)" [style.display]="getRowSpan('Weight', i) ? '' : 'none'">
         {{ data.weight }} </td>
    </ng-container>

    <ng-container matColumnDef="descriptions">
        <th mat-header-cell *matHeaderCellDef> Descriptions </th>
        <td mat-cell *matCellDef="let data"> {{ data.descriptions }} </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> 


</table>

Вот демоверсия

0 голосов
/ 15 мая 2019

Поскольку я не был доволен представленными ответами (особенно с реализацией cacheSpan).

Я придумал что-то более удобное ИМХО, которое выглядит примерно так:

export class TableBasicExample {
  displayedColumns = ['priority', 'status', 'dateCreated', 'testNumber', 'testCurrency', 'testTime'];
  dataSource = DATA;

  spans = {};

  constructor() {
    this.spans = Object.assign({}, {
      priority: this.spanDeep(['priority'], DATA),
      status: this.spanDeep(['priority', 'status'], DATA),
      dateCreated: this.spanDeep(['priority', 'status', 'dateCreated'], DATA)
    });
  }

  spanDeep(paths: string[] | null, data: any[]) {
    if (!paths.length) {
      return [...data]
        .fill(0)
        .fill(data.length, 0, 1);
    }

    const copyPaths = [...paths];
    const path = copyPaths.shift();

    const uniq = uniqWith(data, (a, b) => get(a, path) === get(b, path))
      .map(item => get(item, path));

    return uniq
      .map(uniqItem => this.spanDeep(copyPaths, data.filter(item => uniqItem === get(item, path))))
      .flat(paths.length);
  }

  getRowSpan(path, idx) {
    return this.spans[path][idx];
  }
};

Рабочий пример можно найти здесь: https://stackblitz.com/edit/angular-lnahlh-hw2d3b

0 голосов
/ 24 декабря 2018

Мы должны сказать, сколько там строк, но некоторые строки имеют одинаковые id, и мы будем сортировать и объединять td, если они используют один и тот же идентификатор.Но для ваших данных, скажем, есть несколько строк, а описания могут быть массивными и разделенными.Для этого способа JS не может знать, сколько <tr> должно быть.

2 способа для вас: 1- отформатируйте данные, сохраняйте по одному описанию в каждой строке, так же, как пример данных во втором href, [{id, name, weight, countdescriptions, description},...] и используйте [attr.rowspan]='data.countdescriptions' вместо [attr.rowspan]='getRowSpan(data.id)'.2- Обновите формат содержимого, например <ul><li *ngFor... в описании <td>, и удалите атрибут [attr.rowspan].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...