угловая разбивка материала не работает с расширяемым рядом - PullRequest
0 голосов
/ 23 мая 2018

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

Итак, данные тестовой таблицы предоставляются этой заглушкой:

import { Injectable } from '@angular/core';
import { TableRow } from './table-row';
import { Observable, of } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class TestTableService {

  private testData : TableRow[] = [
    {id:1, name:'pi', value:3.14},
    {id:2, name:'euler', value:2.71},
    {id:3, name:'Feigenbaum constant', value:2.50290},
    {id:4, name:'Mills constant', value:1.30637},
    {id:5, name:'one', value:1},
    {id:6, name:'square root of 2', value:1.41421}
  ];

  constructor() { }

  public getData() : Observable<TableRow[]>
  {
    return of(this.testData);
  }
}

компонент таблицы:

import { Component, OnInit, ViewChild } from '@angular/core';
import { TestTableService } from './../test-table.service';
import { TableRow } from './../table-row';
import {MatPaginator, MatTableDataSource} from '@angular/material';
import { Observable, of} from 'rxjs';
import { animate, state, style, transition, trigger } from '@angular/animations';

@Component({
  selector: 'app-test-table',
  templateUrl: './test-table.component.html',
  styleUrls: ['./test-table.component.css'],
  animations: [
    trigger('detailExpand', [
      state('collapsed', style({ height: '0px', minHeight: '0', visibility: 'hidden' })),
      state('expanded', style({ height: '*', visibility: 'visible' }))
    ]),
  ],
})
export class TestTableComponent implements OnInit {
  tableData : myDataSource<TableRow> = new myDataSource();
  columnsToDisplay = ['id', 'name','value'];
  isExpansionDetailRow = (i: number, row: Object) => row.hasOwnProperty('detailRow');
  expandedElement = null;

  constructor(private testTable : TestTableService) { }

  @ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
    this.paginator = mp;
    this.tableData.paginator = this.paginator;
  }

  //@ViewChild(MatPaginator) paginator: MatPaginator;

  ngOnInit() {
    this.testTable.getData()
      .subscribe(table => this.tableData.data = table);
    //this.tableData.paginator = this.paginator;
  }

  expand(row){
    this.expandedElement = this.expandedElement == row ? null : row;
  }

  //setTimeout(() => this.tableData.paginator = this.paginator);

}

Обратите внимание, что я уже пробовал много решенийпри назначении нумератора страниц but still the result given is this.

html компонента:

<table mat-table [dataSource]="tableData">
  <ng-container matColumnDef="id">
    <th mat-header-cell *matHeaderCellDef> Id </th>
    <td mat-cell *matCellDef="let row"> {{row.id}} </td>
  </ng-container>
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef> Name </th>
    <td mat-cell *matCellDef="let row"> {{row.name}} </td>
  </ng-container>
  <ng-container matColumnDef="value">
    <th mat-header-cell *matHeaderCellDef> Value </th>
    <td mat-cell *matCellDef="let row"> {{row.value}} </td>
  </ng-container>

  <ng-container matColumnDef="details">
    <td mat-cell *matCellDef="let detail"> 
      <!--
      <app-test-table-detail [show]="detail.element == expandedElement" ></app-test-table-detail>
        -->
    </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
  <tr mat-row *matRowDef="let row; columns: columnsToDisplay"
    matRipple
    (click)="expand(row)"></tr>

  <tr mat-row *matRowDef="let row; columns: ['details']; when:isExpansionDetailRow"
    [@detailExpand]="row.element==expandedElement ? 'expanded' : 'collapsed'"
    style="overflow: hidden"></tr>
</table>

<mat-paginator [pageSizeOptions]="[3, 10, 20]" showFirstLastButtons></mat-paginator>

Интересно, что нумератор страниц дает правильные числа, но не имеет никакого эффекта, если яиметь дело с этим в потоке?в функции подключения?

[править] последний код на stackblitz

https://stackblitz.com/edit/angulartableexample?file=src%2Fapp%2Ftest-table%2Ftest-table.component.html

Я также попробовал то, что рекомендует парень, который удалил комментарий, - это использовать AfterViewInitтакже не работает

[Edit] путем отладки случая, в котором нет этой проблемы (без расширяемых строк), разница в этом фрагменте кода, где расширяемые строки используют мою собственную версию DataSourceнет наблюдателей, но с использованием натива есть, я что-то упустил в определении моего источника данных?

enter image description here

1 Ответ

0 голосов
/ 04 июня 2018

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

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

Я также использовал paginatorв качестве простого виджета в представлении, предоставляющего данные подкачки для контроллера.

В конце компонентное представление определяется как:

<table class="mat-table" style="overflow-y:scrol">
  <thead>
    <tr class="mat-header-row">
      <th rowspan="2" class="mat-header-cell" (click)="orderBy('id')">
        ID
      </th>
      <th colspan="2" rowspan="1" class="mat-header-cell">
        But can you do this?
      </th>
    </tr>
    <tr class="mat-header-row">
      <th class="mat-header-cell" (click)="orderBy('name')">
        Name
      </th>
      <th class="mat-header-cell" (click)="orderBy('value')">
        Value
      </th>
    </tr>
  </thead>
  <tbody>
    <tr class="mat-row" *ngFor="let element of showData" (click)="expand(element)">
      <td class="mat-cell"  *ngIf="element.detailRow == undefined">
        {{element.id}}
      </td>
      <td class="mat-cell" *ngIf="element.detailRow == undefined">
        {{element.name}}
      </td>
      <td class="mat-cell" *ngIf="element.detailRow == undefined">
        {{element.value}}
      </td>
      <td colspan="3" class="mat-cell" *ngIf="element.detailRow">
        <app-test-table-detail [show]="true" [id]="element.element.id"></app-test-table-detail>
      </td>
    </tr>
  </tbody>
</table>

<mat-paginator [pageSizeOptions]="[3, 10, 20]" showFirstLastButtons (page)="applyPaging()"></mat-paginator>

и контроллер, но фильтрация еще небыть реализованным

import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { TableRow } from './../table-row';
import { PageEvent, MatPaginator } from "@angular/material";
import { TestTableService } from './../test-table.service';

@Component({
  selector: 'app-native-table',
  templateUrl: './native-table.component.html',
  styleUrls: ['./native-table.component.css']
})
export class NativeTableComponent implements AfterViewInit, OnInit {

  private order : string = "id";
  private reverse : boolean;
  private cacheData : TableRow[] = [];
  private filteredData : TableRow[] = [];
  private pageData : TableRow[] = [];
  private showData : any[] = [];
  private selectedElement : TableRow;
  private filters : any = null;

  constructor(private tableService : TestTableService) { }

  @ViewChild(MatPaginator) paginator: MatPaginator;

  ngOnInit(){
    this.tableService.getData()
      .subscribe(table => this.cacheData = table);
  }

  ngAfterViewInit() {
    this.clearFilters();
  }

  clearFilters() : void{
    this.filters = {
      id : undefined,
      name : ""
    }
    this.applyFilter();
  }

  applyFilter() : void{
    this.filteredData = this.cacheData.slice();
    //do filtering
    this.paginator.length = this.filteredData.length;
    this.applyOrder();
  }

  applyOrder() : void{
    this.filteredData.sort(this.orderRule(this.order,this.reverse))
    this.applyPaging();
  }

  applyPaging() : void{
    this.pageData = this.filteredData.slice(this.paginator.pageIndex*this.paginator.pageSize,(this.paginator.pageIndex+1)*this.paginator.pageSize);
    this.applySelected();
  }

  applySelected() : void{
    this.showData = [];
    this.pageData.forEach(element => element==this.selectedElement ? this.showData.push(element,{detailRow:true,element:element}) : this.showData.push(element))
  }

  orderBy(order : string) : void{
    if(this.order == order){
      this.reverse = !this.reverse
    }
    else{
      this.order = order;
      this.reverse = false;
    }

    this.applyOrder();
  }

  expand(element : TableRow) : void{
    this.selectedElement = this.selectedElement == element ? null : element;
    this.applySelected();
  }

  orderRule(onderIndex,reverse){
    return function(a,b){
      if(a[onderIndex] > b[onderIndex]){
        return reverse ? -1 : 1;
      }
      if(a[onderIndex] < b[onderIndex]){
        return reverse ? 1 : -1;
      }
      return 0;
    }
  }

Я добавил компонент в пример stackblitz , не знаю, почему @ViewChild возвращает undefined для paginator, но локально он работает как задумано

...