Угловая таблица матов, сортировка, фильтрация и разбиение на страницы без изменения внешнего вида таблицы - PullRequest
0 голосов
/ 31 мая 2018

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

Вот мой компонент:

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 голосов
/ 01 марта 2019

Мне нужно было решить очень похожую проблему, которая заключалась в локальной сортировке данных для таблицы mat с сервера с помощью запроса http.post (или http.get), выполняемого из автономной службы.Я использовал MatTableDataSource, чтобы сделать это вопреки советам Андреаса (см. Выше).

Убедитесь, что вы импортировали их в 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/.

Всякий раз, когда вам нужно изменить данные в таблице, вы можете просто вызвать функцию this.updateTable () в app.component.ts и передать переменные черезgetData () в mydata.service.ts для отправки их в качестве параметров в API.Это заняло у меня много времени, чтобы хорошо работать, поэтому надеюсь, что это кому-нибудь поможет.

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

Я думаю, это не работает, потому что источник данных не настроен правильно.Также вам не следует использовать MatTableDataSource для данных на сервере, как описано в

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

, которая содержиточень хороший пример построения таблицы материалов с поиском данных на стороне сервера.

...