【发布时间】:2020-06-08 10:59:21
【问题描述】:
我在 Angular 中有一个自定义数据源,我在其中实现了排序、分页和过滤。所有这些都可以正常工作,但是当我过滤表中的数据时,它只显示当前页面上存在的数据的对应关系。过滤器适用于所有数据,但分页器不会更新表格,也不会显示适当减少的数据。
这是代码
数据模型
import { Sistema } from './sistema'
export class Galassia {
id: number;
nome: string;
imgLink: string;
sistema: Sistema[];
}
服务休息.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { Galassia } from '../model/galassia';
import { catchError, tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ServizioProdottiRESTService {
galassie: Galassia[];
prodottiUrl = 'http://localhost:8080/prodotti';
constructor(private http: HttpClient) { }
getGalassie(): Observable<Galassia[]> {
return this.http.get<Galassia[]>(this.prodottiUrl + '/galassie').pipe(
tap(galaxy => this.galassie = galaxy),
catchError(this.handleError('getGalassie', []))
);
}
private handleError<T>(operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
console.log(error);
this.log(`${operation} failed: ${error.message}`);
return of(result as T);
};
}
private log(message: string) {
console.log('HeroService: ' + message);
}
}
组件.ts
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTable } from '@angular/material/table';
import { ListaProdottiDataSource } from './lista-prodotti-datasource';
import { ServizioProdottiRESTService } from '../servizio-prodotti-rest.service';
import { Galassia } from '../../model/galassia';
@Component({
selector: 'app-lista-prodotti',
templateUrl: './lista-prodotti.component.html',
styleUrls: ['./lista-prodotti.component.css']
})
export class ListaProdottiComponent implements AfterViewInit, OnInit {
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatTable) table: MatTable<Galassia>;
dataSource: ListaProdottiDataSource;
displayedColumns = ['imgLink' ,'nome', 'button'];
constructor(private myService: ServizioProdottiRESTService) {}
ngOnInit() {
this.dataSource = new ListaProdottiDataSource(this.myService);
}
ngAfterViewInit() {
this.table.dataSource = this.dataSource;
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
}
component.html
<div class="mat-elevation-z8 table">
<table mat-table class="full-width-table" matSort aria-label="Elements" [dataSource]="dataSource.data">
<!-- imgLink Column -->
<ng-container matColumnDef="imgLink">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let row"><img [src]="row.imgLink"/></td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="nome">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Nome</th>
<td mat-cell *matCellDef="let row">{{row.nome}}</td>
</ng-container>
<!-- Button Column -->
<ng-container matColumnDef="button">
<th mat-header-cell *matHeaderCellDef><div class="example-header">
<mat-form-field>
<input matInput (keyup)="applyFilter($event)" placeholder="Cosa vuoi cercare?">
</mat-form-field>
</div></th>
<td mat-cell *matCellDef="let row"><img id="freccia" src="../../../assets/freccia.png"></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator #paginator
[length]="dataSource?.data.length"
[pageIndex]="0"
[pageSize]="5"
[pageSizeOptions]="[5, 10, 15]">
</mat-paginator>
</div>
和datasource.ts
import { DataSource } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, merge, BehaviorSubject } from 'rxjs';
import { ServizioProdottiRESTService } from '../servizio-prodotti-rest.service';
import { Galassia } from '../../model/galassia';
export class ListaProdottiDataSource extends DataSource<Galassia> {
data: Galassia[];
paginator: MatPaginator;
sort: MatSort;
get filter(): string { return this.filter$.getValue(); }
set filter(value: string) { this.filter$.next(value); }
filter$: BehaviorSubject<string> = new BehaviorSubject<string>('');
constructor(private myService: ServizioProdottiRESTService) {
super();
this.myService.getGalassie().subscribe(galaxy => this.data = galaxy);
}
connect(): Observable<Galassia[]> {
const dataMutations = [
observableOf(this.data),
this.paginator.page,
this.sort.sortChange,
this.filter$
];
return merge(...dataMutations).pipe(map(() => {
return this.getPagedData(this.getSortedData(this.getFilteredData([...this.data])));
}));
}
disconnect() {}
private getFilteredData(data: Galassia[]) {
return data.filter(d => d.nome.toLowerCase().includes(this.filter));
}
private getPagedData(data: Galassia[]) {
const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
return data.splice(startIndex, this.paginator.pageSize);
}
private getSortedData(data: Galassia[]) {
if (!this.sort.active || this.sort.direction === '') {
return data;
}
return data.sort((a, b) => {
const isAsc = this.sort.direction === 'asc';
switch (this.sort.active) {
case 'nome': return compare(a.nome, b.nome, isAsc);
default: return 0;
}
});
}
}
function compare(a: string | number, b: string | number, isAsc: boolean) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
问题的一些图像
This is the first page before filtering
This is the second page before filtering
当我在引用第二页元素的第一页上应用过滤器时,会发生这种情况
页面是空的,但是如果我转到第二页,则会显示元素
从页面索引中也可以看到,这些索引没有更新,因为它们基于完整的元素数组,这是另一个问题
【问题讨论】:
-
给我们看一些代码?,我们不能帮你修复我们看不到的东西(我指的不是页面,而是代码)
-
@Bargros 我马上去做
-
@Bargros 编辑完成!
标签: angular filter angular-material datasource paginator