下拉过滤器在PrimeNG控件中的行组表中不起作用



在我的angular项目中,我已经安装了PrimeNG controls版本11.4.4。我使用Table控件来创建表格数据,以显示具有可折叠样式的组中的行。

现在,我在标题行之前添加了一个文本框和下拉控件来过滤表数据。但问题是与行组表数据,过滤与下拉并不总是工作。只有下拉项"附件"在工作。但是对于其他下拉项,过滤不起作用。

这是我的GitHub Repo。

谁能请运行代码看到问题,并建议我如何解决这个问题?

<h2>Table with Rog Group</h2>
<p-table #dt2 [columns]="selectedColumns" [value]="products" sortField="category" sortMode="single" (onSort)="onSort()"
dataKey="category" styleClass="p-datatable-gridlines p-datatable-striped">
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns">
{{col.header}}
</th>
</tr>
<tr>
<th *ngFor="let col of columns" [ngSwitch]="col.field">
<p-columnFilter *ngSwitchCase="'code'" type="text" field="code" matchMode="contains"
(input)="applyFilter1($event, 'code', 'contains')">
</p-columnFilter>
<p-columnFilter *ngSwitchCase="'name'" type="text" field="name" matchMode="contains"
(input)="applyFilter1($event, 'name', 'contains')">
</p-columnFilter>
<p-columnFilter *ngSwitchCase="'category'" field="category" matchMode="equals" [showMenu]="false">
<ng-template pTemplate="filter" let-value let-filter="filterCallback">
<p-dropdown [ngModel]="value" [options]="categories" (onChange)="filter($event.value)" placeholder="Any"
[showClear]="true">
<ng-template let-option pTemplate="item">
<div class="p-multiselect-representative-option">
<span class="p-ml-1">{{option.label}}</span>
</div>
</ng-template>
</p-dropdown>
</ng-template>
</p-columnFilter>
<p-columnFilter *ngSwitchCase="'quantity'" type="text" field="quantity" matchMode="equals"
(input)="dt2.filter($event.target.value1)">
</p-columnFilter>
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex" let-expanded="expanded">
<tr *ngIf="rowGroupMetadata[rowData.category].index === rowIndex">
<td colspan="4">
<button type="button" pButton pRipple [pRowToggler]="rowData"
class="p-button-text p-button-rounded p-button-plain p-mr-2"
[icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
<span class="p-text-bold p-ml-2">{{rowData.category}}</span>
</td>
</tr>
</ng-template>
<ng-template pTemplate="rowexpansion" let-rowData let-columns="columns">
<tr>
<td *ngFor="let col of columns">
<span>{{rowData[col.field]}}</span>
</td>
</tr>
</ng-template>
</p-table>

TS文件:

import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { Table } from 'primeng/table';
import { Product } from '../_models/product.model';
import { ProductService } from '../_services/product.service';
@Component({
selector: 'app-row-group-grid',
templateUrl: './row-group-grid.component.html',
styleUrls: ['./row-group-grid.component.css']
})
export class RowGroupGridComponent implements OnInit {
products: Product[] = [];
cols: any[] = [];
_selectedColumns: any[] = [];
categories: any[] = [];
rowGroupMetadata: any;
@ViewChild('dt2') dt2!: Table;
constructor(private productService: ProductService) { }
ngOnInit() {
this.productService.getProductsSmall().then(data => {
this.products = data;
this.updateRowGroupMetaData();
});
this.cols = [
{ field: 'code', header: 'Code' },
{ field: 'name', header: 'Name' },
{ field: 'category', header: 'Category' },
{ field: 'quantity', header: 'Quantity' }
];
this._selectedColumns = this.cols;
this.categories = [      
{ label: "Clothing", value: "Clothing" },
{ label: "Electronics", value: "Electronics" },
{ label: "Fitness", value: "Fitness" },
{ label: "Accessories", value: "Accessories" },
];
}
@Input() get selectedColumns(): any[] {
return this._selectedColumns;
}
set selectedColumns(val: any[]) {
//restore original order
this._selectedColumns = this.cols.filter(col => val.includes(col));
}
applyFilter1($event: any, field: string, matchMode: string) {
let value = ($event.target as HTMLInputElement)?.value;
this.dt2.filter(value, field, matchMode);
}
onSort() {
this.updateRowGroupMetaData();
}
updateRowGroupMetaData() {
this.rowGroupMetadata = {};
if (this.products) {
for (let i = 0; i < this.products.length; i++) {
let rowData = this.products[i];
let category1 = rowData.category;
if (i == 0) {
this.rowGroupMetadata[category1] = { index: 0, size: 1 };
}
else {
let previousRowData = this.products[i - 1];
let previousRowGroup = previousRowData.category;
if (category1 === previousRowGroup)
this.rowGroupMetadata[category1].size++;
else
this.rowGroupMetadata[category1] = { index: i, size: 1 };
}
}
}
}
}

问题

检查rowGroupMetadata中的这个逻辑在表被过滤时崩溃。

<tr *ngIf="rowGroupMetadata[rowData.category].index === rowIndex">
<td colspan="4">
<button type="button" pButton pRipple [pRowToggler]="rowData"
class="p-button-text p-button-rounded p-button-plain p-mr-2"
[icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
<span class="p-text-bold p-ml-2">{{rowData.category}}</span>
</td>
</tr>

您需要确保在筛选表时也更新了rowGroupMetadata.


解决方案对于HTML部分,不是直接调用filter回调,而是通过解析filter回调和$event.value来调用dropdownFilter自定义函数。

.component.html

<p-columnFilter *ngSwitchCase="'category'" field="category" matchMode="equals" [showMenu]="false">
<ng-template pTemplate="filter" let-value let-filter="filterCallback">
<p-dropdown [options]="categories" (onChange)="dropdownFilter(filter, $event.value)" placeholder="Any" [showClear]="true">
<ng-template let-option pTemplate="item">
<div class="p-multiselect-representative-option">
<span class="p-ml-1">{{option.label}}</span>
</div>
</ng-template>
</p-dropdown>
</ng-template>
</p-columnFilter>
  1. dropDownFilter方法接受filter回调和value参数。在此方法中,表经过过滤后,将通过将filteredValue(过滤结果)改为updateRowGroupMetaData方法。
  2. 修改
  3. updateRowGroupMetaData方法,将rows作为可选参数接收。当收到rows时,将基于它更新rowGroupMetadata。否则,使用this.products保持现有逻辑。

.component.ts

updateRowGroupMetaData(rows?: Product[]) {
let products = rows ?? this.products;
this.rowGroupMetadata = {};
if (products) {
for (let i = 0; i < products.length; i++) {
let rowData = products[i];
let category1 = rowData.category;
if (i == 0) {
this.rowGroupMetadata[category1] = { index: 0, size: 1 };
}
else {
let previousRowData = products[i - 1];
let previousRowGroup = previousRowData.category;
if (category1 === previousRowGroup)
this.rowGroupMetadata[category1].size++;
else
this.rowGroupMetadata[category1] = { index: i, size: 1 };
}
}
}
}
dropdownFilter(filter: (a: string) => void, value: string) {
filter(value);
this.updateRowGroupMetaData(this.dt2.filteredValue);
}

StackBlitz的样例解决方案

最新更新