Сортировка в столбце "Итого" не работает angular мат-таблица - PullRequest
0 голосов
/ 03 августа 2020

Моя таблица mat работает нормально, все мои столбцы сортируются, за исключением моего последнего столбца, который вычисляет значения суммы из других столбцов с использованием уменьшения.

Я вроде застрял в этой проблеме, но сначала, потому что метод сокращения происходит после жизненного цикла OnInit, но даже если я объявляю this.dataSource.data = this.data в ngAfterViewInit, не работает.

Мой HTML шаблон:

image

TypeScript file

import { Observable, BehaviorSubject } from 'rxjs';
import { SubCollection } from 'model/item-tree/collection';
import { MatSort, MatPaginator, MatTableDataSource } from '@angular/material';
import { Component, ViewChild, Input, OnInit, ChangeDetectionStrategy, AfterViewInit, OnChanges } from '@angular/core';

@Component({
  selector: 'app-collection-steps-report-subcollection-table',
  templateUrl: './collection-steps-report-subcollection-table.component.html',
  styleUrls: ['./collection-steps-report-subcollection-table.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class CollectionStepsReportSubcollectionTableComponent implements OnInit {

  @ViewChild(MatSort, { static: true }) sort: MatSort;
  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;

  @Input() data: any[];
  @Input() subCollection: SubCollection;
  @Input() filterBy$: Observable<string>;
  @Input() stepsName$: BehaviorSubject<string[]>;

  public columns: string[];
  public dataSource = new MatTableDataSource();

  public ngOnInit(): void {
    this.dataSource.filterPredicate = (data: any, filter: string): boolean => {
      if (filter === 'id') {
        return true;
      }
      const id = data['id'] as string;
      const name = data['name'] as string;
      const matchId = (id) ? id.trim().toLowerCase().indexOf(filter) !== -1 : true;
      const matchName = (name) ? name.trim().toLowerCase().indexOf(filter) !== -1 : true;
      return matchName || matchId;
    };
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
    this.filterBy$.subscribe(
      filter => {
        this.dataSource.filter = filter.trim().toLowerCase();

        if (this.dataSource.paginator) {
          this.dataSource.paginator.firstPage();
        }
      }
    );

    this.stepsName$.subscribe(
      sn => {
        this.columns = ['coverUrl', 'id', 'name', ...sn, 'total'];
      }
    );
    this.dataSource.data = this.data;
  }

  public hasData(): boolean {
    return Array.isArray(this.data) && this.data.length > 0;
  }

  public getTotalDataOfItem(itemId: string): number {
    const item = this.data.find(i => i.id === itemId);
    return this.stepsName$.getValue().reduce((acc, stepName) => {
      return acc += item[stepName];
    }, 0);
  }

  public getTotalDataOfAll(): number {
    return this.data.reduce(
      (acc1, item) => acc1 += this.stepsName$.getValue().reduce((acc2, stepName) => acc2 += item[stepName], 0)
    , 0);
  }

  public getDataOfItemForStepName(itemId: string, stepName: string): string {
    return this.data.find(i => i.id === itemId)[stepName];
  }

  public getTotalDataOfStep(step: string): number {
    return this.data.reduce((acc, item) => acc += item[step], 0);
  }
}

Рад получить совет или помочь прояснить мой разум, чтобы решить эту проблему :) Thx!

1 Ответ

0 голосов
/ 05 августа 2020

После нескольких попыток я обнаружил, что моя проблема заключалась в том, что столбец «total» не был частью объекта «item».

Поэтому я реализую метод map для своих данных, назначая возврат функции getTotalDataOfItem в мой новый массив данных внутри ngOnInit, и он отлично работает!

Поскольку в моем элементе теперь есть столбец 'total', мне пришлось реорганизовать шаблон HTML для рендеринга item.total в <td> вместо возврата getTotalDataOfItem(item.id)

Чтобы все работало, просто добавьте этот код внутри ngOnInit в файл TS

const dataWithTotal = this.data.map(
  value => {
    return {
      ...value, total: this.getTotalDataOfItem(value['id'])
    };
  }
);

Затем выполните рефакторинг файла HTML следующим образом

<td mat-cell *matCellDef="let item">{{ 'stepsReportAverageTimeSpentDaysUnit' | translate:{ numberDays: item.total } }}</td>

Затем наслаждайтесь своей матовой таблицей, правильно сортируя все столбцы :)

...