下拉过滤器无法与 PrimeNG 控件中的行组 table 一起使用
Dropdown filter is not working in with Row Group table in PrimeNG controls
在我的 angular 项目中,我安装了 PrimeNG 控件版本 11.4.4。我已使用 Table 控件创建表格数据,以显示组中的行并具有可折叠样式。
现在我在 header 行之前添加了一个文本框和下拉控件来过滤 table 数据。但问题在于行组 table 数据,使用下拉列表进行过滤并不总是有效。只有下拉项附件在工作。但是对于其他下拉项过滤不起作用。
任何人都可以运行查看问题的代码并向我建议如何解决这个问题吗?
<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
中的这个逻辑在过滤 table 时崩溃。
<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
在过滤 table 时也会更新 。
解决方案
对于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>
dropDownFilter
方法接受 filter
回调和 value
参数。在这个方法中,table被过滤后,会通过
filteredValue
(过滤后的结果)到 updateRowGroupMetaData
方法。
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);
}
在我的 angular 项目中,我安装了 PrimeNG 控件版本 11.4.4。我已使用 Table 控件创建表格数据,以显示组中的行并具有可折叠样式。
现在我在 header 行之前添加了一个文本框和下拉控件来过滤 table 数据。但问题在于行组 table 数据,使用下拉列表进行过滤并不总是有效。只有下拉项附件在工作。但是对于其他下拉项过滤不起作用。
任何人都可以运行查看问题的代码并向我建议如何解决这个问题吗?
<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
中的这个逻辑在过滤 table 时崩溃。
<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
在过滤 table 时也会更新 。
解决方案
对于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>
dropDownFilter
方法接受filter
回调和value
参数。在这个方法中,table被过滤后,会通过filteredValue
(过滤后的结果)到updateRowGroupMetaData
方法。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);
}