如何使用 PrimeNG 在标题中显示保存的过滤器?

Posted

技术标签:

【中文标题】如何使用 PrimeNG 在标题中显示保存的过滤器?【英文标题】:How to display saved filters in headers with PrimeNG? 【发布时间】:2020-03-02 05:55:39 【问题描述】:

我可以使用 stateStorage="local" stateKey="myKey" 在本地保存过滤器。因此,当用户离开组件并返回时,仍然会根据他们设置的过滤器过滤数据。

问题是,用户不再知道他们在过滤什么,因为过滤器标题不再向他们显示任何内容,只是默认标签。我可以通过本地存储访问过滤器,并使用localStorage.removeItem("myKey"); 将其删除,但我终生无法弄清楚如何让此过滤器信息显示在过滤器标题中。正如另一个答案中所建议的,我们没有使用lazyLoad。您会认为这将在任何时候保存过滤器时构建,因为不知道您在过滤什么似乎是一个主要缺陷。

为了更清楚起见,我附上了下面的 primeFaces 文档。如果您从多选下拉列表中选择“红色”、“白色”和“绿色”,它将在上方的标题(红色、白色、绿色)中显示您选择的过滤器。如果用户保存了过滤器(包括文本输入和下拉菜单),我需要在用户输入组件时显示此信息。

https://www.primefaces.org/primeng/#/table/filter

我正在使用多选下拉过滤器、文本输入以及日历过滤器。这是 html 的 sn-p,其中包括这三种过滤器类型的示例:

    <th *ngFor="let col of columns" [ngSwitch]="col.field">                                               
      <input *ngSwitchCase="'userID'" pInputText type="text" size="12" placeholder="contains" (input)="table.filter($event.target.value, col.field, col.filterMatchMode)" [value]="table.filters['userID'] ? table.filters['userID'].value : ''">       
      <div class="ui-g ui-fluid">
        <p-calendar #calendar1 class="ui-fluid" *ngSwitchCase="'myDate'" [monthNavigator]="true" [showOnFocus]="false" [yearNavigator]="true" yearRange="2010:2060" [showIcon]="true" 
          [showOtherMonths]="false" [showButtonBar]="true" [appendTo]="attach"  [style]="'overflow': 'visible'" 
          [(ngModel)]="calendar1Filter" 
          (ngModelChange)="table.filter($event, 'myDate', calendar1Option)"                                                                                 
          (onSelect)="table.filter($event, 'myDate', calendar1Option)">
            <p-footer>  
                <div class="ui-grid-row">
                    <div class="ui-grid-col-3"><label style="font-weight: bold; color: #337ab7">Mode:</label></div>                     
                    <div class="ui-grid-col-6"><p-dropdown [options]="calendar1Options" [style]="'width':'60px', 'padding-top': '0px'" [(ngModel)]="calendar1Option" (onChange)="onChangeModCalOpt(calendar1, 1)" ></p-dropdown> </div>
                </div>
             </p-footer>
         </p-calendar>   
       </div>                                  
      <div class="ui-fluid">
        <p-multiSelect *ngSwitchCase="'myDropdown'" appendTo="body" [options]="dropdownOptions" pInputText type="text" size="12" [style]="'width':'100%'" defaultLabel="All" [(ngModel)]="myDropdownFilter" (onChange)="table.filter($event.value, col.field, 'in')"></p-multiSelect>
      </div>
     </th>

【问题讨论】:

可以提供表格的component.html吗?过滤器是在标题输入、选择框中还是两者兼而有之? 添加了我正在使用的过滤器示例。它是选择框和输入以及日历。 【参考方案1】:

我差不多一年前就这样做了;它涉及一些棘手的代码,如下所示,因为 table 元素位于 *ngIf 指令下方。我不确定你的情况是否相同,但如果是,这就是我必须做的才能让它工作。在示例中,我有一个 fooTable,它在 status 列上有一个自定义过滤器。

foo.component.ts:

import  ChangeDetectorRef, Component, ViewChild  from "@angular/core";

@Component(
    selector    : 'foo',
    templateUrl : 'foo.component.html'
)
export class FooComponent 
    // members /////////////////////////////////////////////////////////////////////////////////////////////////////////
    showFooTable: boolean  = true;
    statusFilter: string[] = [];

    // constructor(s) //////////////////////////////////////////////////////////////////////////////////////////////////
    constructor(private cd: ChangeDetectorRef)  

    // getters and setters /////////////////////////////////////////////////////////////////////////////////////////////
    /**
     * Due to the Angular lifecycle, we have to do some tricky things here to pull the filters from the session,
     * if they are present. The workarounds done in this function are as follows:
     *
     * 1) Wait until the element is accessible. This is not until the *ngIf is rendered, which is the second call to
     *    this function. The first call is simply 'undefined', which is why we check for that and ignore it.
     * 2) Check and see if the filters for this object are even part of the template. If not, just skip this step.
     * 3) If we find the filters in the session, then change this object's filters model to equal it and call the change
     *    detection manually to prevent Angular from throwing an ExpressionChangedAfterItHasBeenCheckedError error
     * @param fooTable the reference to the foo table template
     */
    @ViewChild('fooTable') set fooTable(fooTable: any) 
        if(fooTable != undefined) 
            let filters = fooTable.filters['status'];
            if (filters != undefined && filters.value != undefined) 
                this.statusFilter = filters.value;
            
            this.cd.detectChanges();
        
    

foo.component.html:

<ng-container *ngIf="showFooTable">
    <div id="filters">
        <p-checkbox [(ngModel)]="statusFilter" value="up"      (onChange)="fooTable.filter(statusFilter, 'status', 'in')"></p-checkbox> Up
        <p-checkbox [(ngModel)]="statusFilter" value="down"    (onChange)="fooTable.filter(statusFilter, 'status', 'in')"></p-checkbox> Down
        <p-checkbox [(ngModel)]="statusFilter" value="unknown" (onChange)="fooTable.filter(statusFilter, 'status', 'in')"></p-checkbox> Unknown
    </div>

    <p-table #fooTable
             stateStorage="session"
             stateKey="foo-table-state">
    </p-table>
</ng-container>

【讨论】:

【参考方案2】:

Turbo 表格过滤器可以像这样访问。 table.filters['myColumn']?.value。您需要在标题中设置输入值,[value]="table.filters[col.field]?.value"

...
<tr>
    <th *ngFor="let col of columns" [ngSwitch]="col.field" class="ui-fluid">
        <input pInputText 
               type="text"
               (input)="table.filter($event.target.value, col.field, col.filterMatchMode)"
               [value]="table.filters[col.field]?.value">
    </th>
</tr>
...

https://www.primefaces.org/primeng/#/table/state

【讨论】:

【参考方案3】:

刚刚想通了。我最终做的是将默认标签附加到这样的模型:

<p-multiSelect [defaultLabel]="table.filters[col.field]?.value || 'All'">

如果表格在其状态中具有过滤器值,它将填充标签,否则默认为“全部”。

【讨论】:

以上是关于如何使用 PrimeNG 在标题中显示保存的过滤器?的主要内容,如果未能解决你的问题,请参考以下文章

primeNG 预设值不起作用,它显示为 [object object]

是否可以使用 PrimeNG DataTable 添加自定义过滤功能?

primeng 文本编辑器图标和标签未显示

Primeng - 对话服务将数据传递给对话组件

PrimeNG - 通过按钮单击发送表单数据和文件上传数据

受“错误:找不到不同的支持对象”影响的 Primeng