角度mat-table,排序,过滤和分页不会改变表格外观

时间:2018-05-31 20:18:52

标签: angular typescript html-table angular-material

我试图关注material example并在我自己的数据上实现它,表格会像它应该的那样渲染,但分页,排序和过滤都不起作用。您可以在过滤器框中书写,更改每页的数量,然后按进行排序并获得向上或向下的箭头,但表格中没有任何变化。我认为这与我如何加载数据有关,但我不确定究竟发生了什么。

这是我的组成部分:

import { Component, OnInit, ViewChild } from '@angular/core';
import { first } from 'rxjs/operators';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator, MatSort } from '@angular/material';

import { Invoice } from '../_models';
import { InvoiceService } from '../_services';

@Component({
  selector: 'app-invoices',
  templateUrl: './invoices.component.html',
  styleUrls: ['./invoices.component.css']
})
export class InvoicesComponent implements OnInit {
  displayedColumns=['rating', 'amount', 'debtor', 'serial', 'dateout', 'expiration', 'daysleft', 'fid']
  invoices: Invoice[] = [];
  dataSource= new MatTableDataSource<Invoice>(this.invoices);

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  constructor(
    private invoiceService: InvoiceService
  ) { }

  ngOnInit() {
    this.loadInvoices();
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }
  private loadInvoices(){
    this.invoiceService.getUserInvoices().pipe(first()).subscribe(invoices => {
      this.invoices=invoices;
    });

  }
  applyFilter(filterValue: string) {
    filterValue = filterValue.trim(); // Remove whitespace
    filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
    this.dataSource.filter = filterValue;
    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }

}

这是html:

<h3> All Uploaded invoices:</h3>
<mat-form-field>
    <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
<div class="mat-elevation-z8">
  <mat-table #table [dataSource]="invoices" matSort class="mat-elevation-z8">

    <ng-container matColumnDef="rating">
      <mat-header-cell *matHeaderCellDef mat-sort-header> Rating </mat-header-cell>
      <mat-cell *matCellDef="let invoice"> {{invoice.rating}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="amount">
      <mat-header-cell *matHeaderCellDef mat-sort-header> Amount </mat-header-cell>
      <mat-cell *matCellDef="let invoice"> {{invoice.amount}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="debtor">
      <mat-header-cell *matHeaderCellDef> Debtor </mat-header-cell>
      <mat-cell *matCellDef="let invoice"> {{invoice.debtor}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="serial">
      <mat-header-cell *matHeaderCellDef> Serial </mat-header-cell>
      <mat-cell *matCellDef="let invoice"> {{invoice.serial}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="dateout">
      <mat-header-cell *matHeaderCellDef> Dateout </mat-header-cell>
      <mat-cell *matCellDef="let invoice"> {{invoice.dateout}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="expiration">
      <mat-header-cell *matHeaderCellDef> Expiration </mat-header-cell>
      <mat-cell *matCellDef="let invoice"> {{invoice.expiration}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="daysleft">
      <mat-header-cell *matHeaderCellDef mat-sort-header > Days left </mat-header-cell>
      <mat-cell *matCellDef="let invoice"> {{invoice.daysleft}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="fid">
      <mat-header-cell *matHeaderCellDef> Fid </mat-header-cell>
      <mat-cell *matCellDef="let invoice"> {{invoice.fid}} </mat-cell>
    </ng-container>


    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
  </mat-table>
  <mat-paginator [pageSizeOptions]="[3, 100, 200]" showFirstLastButtons></mat-paginator> 
</div>
<p><a [routerLink]="['/login']">Logout</a></p>

最后是发票型号:

export class Invoice {
    id: any;
    rating: any;
    serial: any;
    amount: any;
    debtor: any;
    dateout: any;
    expiration: any;
    daysleft: any;
    fid: any;
    invoicefile: File;
}

对可能出现的问题的任何见解?

2 个答案:

答案 0 :(得分:1)

我猜它不起作用,因为数据源配置不正确。此外,您不应将MatTableDataSource用于基于服务器的数据,如

中所述

https://blog.angular-university.io/angular-material-data-table/

包含非常好的步骤来构建带有服务器端数据检索的Material Table示例。

答案 1 :(得分:0)

我需要解决一个非常类似的问题,该问题涉及通过独立服务执行的http.post(或http.get)请求从服务器本地为mat-table排序数据。我根据MatreaDataSource的建议(以上)。

确保将它们导入到app.module.ts:


import { HttpClientModule } from '@angular/common/http';
import { MatTableModule } from '@angular/material/table';
import { MatSortModule } from '@angular/material';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';

@NgModule({

  ....,

  imports: [
    ....,
    HttpClientModule,
    MatTableModule,
    MatSortModule,
    MatProgressSpinnerModule,
  ],

  ....,

})

我的html(app.component.html):

<div class="example-container mat-elevation-z8">

    <div class="example-loading-shade"
       *ngIf="isLoadingResults">
        <mat-spinner *ngIf="isLoadingResults" color="accent"></mat-spinner>
    </div>

    <div class="example-table-container">
      <table mat-table matSort [dataSource]="datasrc" hover="true" class="example-table">
        <ng-container matColumnDef="name" sticky>
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
          <td mat-cell *matCellDef="let element"> {{element.name}} </td>
        </ng-container>
        <ng-container matColumnDef="age">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Age </th>
          <td mat-cell *matCellDef="let element"> {{element.age}} </td>
        </ng-container>
        <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
        <tr mat-row 
            *matRowDef="let row; let i = index; columns: displayedColumns;" 
            (click)="onSelectRow(i)"
            class="example-element-row"></tr>
      </table>
    </div>
</div>

应用程序组件(app.component.ts):

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { merge, Observable, of as observableOf } from 'rxjs';
import { catchError, map, startWith, switchMap } from 'rxjs/operators';

import { MatSort, MatTableDataSource, MatTable } from '@angular/material';
import { MatTableModule } from '@angular/material/table';

import { MyDataService } from './mydata.service';
import { Person, RootObject } from './mydata.interface';

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

  displayedColumns: string [] = [
    'name',
    'age',
  ];

  mydataDB: MyDataService | null;
  dataSource: Person[] = [];
  datasrc = new MatTableDataSource<object>(this.dataSource);
  isLoadingResults = true;

  @ViewChild(MatSort) sort: MatSort;
  @ViewChild(MatTable) table: MatTable<any>;

  constructor(
    private myDataService: MyDataService,
    private http: HttpClient
    ) { }

  ngAfterViewInit() {
    this.updateTable();
  }

  updateTable() {
    this.mydataDB = new MyDataService(this.http);
      merge(this.sort.sortChange)
        .pipe(
          startWith({}),
          switchMap(() => {
            this.isLoadingResults = true;
            return this.mydataDB!.getData();
          }),
          map(data => {
            this.isLoadingResults = false;
            return data;
          }),
          catchError(() => {
            this.isLoadingResults = false;
            return observableOf([]);
          })
        ).subscribe(data => {
          this.dataSource = data['response'];

          this.datasrc = new MatTableDataSource(this.dataSource);
          this.datasrc.sort = this.sort;
          this.table.renderRows();
         });
  }
}

接口(mydata.interface.ts):

export interface RootObject {
    response: Person
}

export interface Person {
    name: string;
    age: number;
}

我的数据服务(mydata.service.ts):

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, Subscriber } from 'rxjs';
import { tap, map, filter } from 'rxjs/operators';

import { RootObject } from './remittances.interface';

@Injectable()
export class MyDataService{
    //Change this to the url you need
    public httpRoot = 'http://www.myapi.com/api/';
    private postBody: {};

    constructor(
        private http: HttpClient,
        ) {}

    getData(): Observable<RootObject[]> {
        //Add any APi parameters here if needed
        this.postBody = {
            "name":"getPeopleAPI",
            "params":{
                "filter":"country"
            }
        };
        return this.http.post<RootObject[]>(
            this.httpRoot,
            this.postBody,
            {
                headers: new HttpHeaders({
                    'Content-Type': 'application/json',
                })
            }
        );
    }
}

最后是CSS(app.component.css):

.example-container {
  position: relative;
  min-height: 400px;
}

.example-table-container {
  position: relative;
  max-height: 400px;
  overflow: auto;
}

.example-loading-shade {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.15);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Column Widths */
.mat-column-number,
.mat-column-state {
  max-width: 64px;
}

.mat-column-created {
  max-width: 124px;
}

您将需要修改接口以匹配来自API的所需数据,并将其适当地适合表。 http://www.jsontots.com/是一个很好的工具。

每当需要更改表中的数据时,只需在app.component.ts中调用this.updateTable()函数并将变量传递到mydata.service.ts中的getData()即可将它们作为参数发送给API。这花了我很长一段时间才能很好地工作,因此希望这对某人有帮助。