Я хочу реализовать в своем проекте сортировку, разбиение по страницам и фильтрацию. Когда я иду фильтровать данные в таблице, мне показывается только соответствие данных, присутствующих на текущей странице. Допустим, на первой странице есть только 5 данных. , фильтр работает только на них. Это не работает на всей странице.
Вот коды
ТС:
export class ListComponent extends BaseComponent implements OnInit {
constructor(spinner: NgxSpinnerService,
private productService: ProductService,
private alertifyService: AlertifyService,
private dialogService: DialogService) {
super(spinner)
}
displayedColumns: string[] = ['name', 'stock', 'price', 'createdDate', 'updatedDate', 'photos', 'qrcode', 'edit', 'delete'];
dataSource: MatTableDataSource<List_Product> = null;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
async getProducts() {
this.showSpinner(SpinnerType.BallAtom);
const allProducts: { totalProductCount: number; products: List_Product[] } = await this.productService.read(this.paginator ? this.paginator.pageIndex : 0, this.paginator ? this.paginator.pageSize : 5, () => this.hideSpinner(SpinnerType.BallAtom), errorMessage => this.alertifyService.message(errorMessage, {
dismissOthers: true,
messageType: MessageType.Error,
position: Position.TopRight
}))
this.dataSource = new MatTableDataSource<List_Product>(allProducts.products);
this.paginator.length = allProducts.totalProductCount;
}
addProductImages(id: string) {
this.dialogService.openDialog({
componentType: SelectProductImageDialogComponent,
data: id,
options: {
width: "1400px"
}
});
}
async pageChanged() {
await this.getProducts();
}
async ngOnInit() {
await this.getProducts();
}
showQRCode(productId: string) {
this.dialogService.openDialog({
componentType: QrcodeDialogComponent,
data: productId,
afterClosed: () => { }
})
}
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
filter(filterValue: string) {
filterValue = filterValue.trim();
filterValue = filterValue.toLowerCase();
this.dataSource.filter = filterValue;
}
}
HTML
<div class = "example-header">
<mat-form-field>
<input matInput (keyup) = "filter($any($event.target).value)" placeholder = "Filter">
</mat-form-field>
</div>
<div class = " mat-elevation-z8">
<table mat-table [dataSource] = "dataSource" matSort>
<ng-container matColumnDef = "name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef = "let element"> {{element.name}} </td>
</ng-container>
<ng-container matColumnDef = "stock">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Stock </th>
<td mat-cell *matCellDef = "let element"> {{element.stock}} </td>
</ng-container>
<ng-container matColumnDef = "price">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Price </th>
<td mat-cell *matCellDef = "let element"> {{element.price}}$ </td>
</ng-container>
<ng-container matColumnDef = "createdDate">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Created Date </th>
<td mat-cell *matCellDef = "let element"> {{element.createdDate}} </td>
</ng-container>
<ng-container matColumnDef = "updatedDate">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Updated Date </th>
<td mat-cell *matCellDef = "let element"> {{element.updatedDate}} </td>
</ng-container>
<ng-container matColumnDef = "photos">
<th mat-header-cell *matHeaderCellDef width = "30"> </th>
<td mat-cell *matCellDef = "let element"> <img style = "cursor:pointer" (click) = "addProductImages(element.id)" src = "../../../../../assets/add_a_photo_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.png" width = "25" height = "25" /> </td>
</ng-container>
<ng-container matColumnDef = "qrcode">
<th mat-header-cell *matHeaderCellDef width = "30"> </th>
<td mat-cell *matCellDef = "let element"> <img style = "cursor:pointer" src = "../../../../../assets/qrcode.png" width = "25" height = "25" (click) = "showQRCode(element.id)" /> </td>
</ng-container>
<ng-container matColumnDef = "edit">
<th mat-header-cell *matHeaderCellDef width = "30"> </th>
<td mat-cell *matCellDef = "let element"> <img style = "cursor:pointer;" src = "../../../../../assets/update_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.png" width = "25" height = "25" /> </td>
</ng-container>
<ng-container matColumnDef = "delete">
<th mat-header-cell *matHeaderCellDef width = "30"> </th>
<td mat-cell *matCellDef = "let element"
appDelete
[id] = "element.id"
(callback) = "getProducts()"
controller = "products">
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef = "displayedColumns"></tr>
<tr mat-row *matRowDef = "let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator (page) = "pageChanged()"
[pageSizeOptions] = "[5, 10, 20, 50, 100]"
showFirstLastButtons
aria-label = "Select page of periodic elements">
</mat-paginator>
</div>
Вы неправильно применяете фильтрацию. Вам необходимо отправить информацию о фильтрации на серверную часть в качестве параметра запроса. Затем отфильтруйте данные на бэкэнде и верните первую страницу и т. д.
Я бы порекомендовал вам выполнить вышеуказанные изменения, если в этом нет необходимости, воспользуйтесь описанным ниже подходом.
В настоящее время проблема с вашим кодом заключается в том, что вы сбрасываете отфильтровать через строку ниже:
this.dataSource = new MatTableDataSource<List_Product>(allProducts.products);
Мы можем повторно применить фильтр после воссоздания источника данных. Мы создаем клон, используя StructuredClone:
async getProducts() {
this.showSpinner(SpinnerType.BallAtom);
const allProducts: { totalProductCount: number; products: List_Product[] } = await this.productService.read(this.paginator ? this.paginator.pageIndex : 0, this.paginator ? this.paginator.pageSize : 5, () => this.hideSpinner(SpinnerType.BallAtom), errorMessage => this.alertifyService.message(errorMessage, {
dismissOthers: true,
messageType: MessageType.Error,
position: Position.TopRight
}))
// take a backup of the filter as a clone.
const filterClone = structuredClone(this.dataSource.filter);
const sortClone = structuredClone(this.dataSource.sort);
this.dataSource = new MatTableDataSource<List_Product>(allProducts.products);
if (filterClone) {
this.dataSource.filter = filterClone;
}
if (sortClone) {
this.dataSource.sort = sortClone;
}
this.dataSource.paginator = this.paginator;
this.paginator.length = allProducts.totalProductCount;
}
Вы совершенно правы. Я решил проблему, внеся несколько изменений в серверную часть. Большое спасибо за предоставленную ценную информацию.