Primeng table filter not working on column with nested object

南楼画角 提交于 2020-01-25 07:05:46

问题


I have a primeng table where on column value is obtained from a nested object.I am unable to filter the table using that column value.The filter works fine if enter value present in other columns.Please help.Thanks in advance.

Here is my typescript:

this.cols = [
      { field: 'name', header: 'Name' },
      { field: 'email', header: 'Email' },
      { field: 'phnNumber', header: 'Contact No' },
      { field: 'grades[0].grade1', header: 'Grade' },

    ];

here is my filter:

   <div class="col-md-6">
    <p-table [columns]="cols" #dt [value]="students" [autoLayout]="true" [paginator]="true" [rows]="10">
        <ng-template pTemplate="caption">
            <div style="text-align: right">
                <i class="fa fa-search" style="margin:4px 4px 0 0"></i>
                <input type="text" pInputText size="30" placeholder="Search" (input)="dt.filterGlobal($event.target.value, 'contains')" class="filter">
            </div>
        </ng-template>
        <ng-template pTemplate="header" let-columns>
            <tr>
                <th class="row-header" *ngFor="let col of columns" [pSortableColumn]="col.field">
                    {{col.header}}
                    <p-sortIcon class="" [field]="col.field" ariaLabel="Activate to sort" ariaLabelDesc="Activate to sort in descending order" ariaLabelAsc="Activate to sort in ascending order">
                    </p-sortIcon>
                </th>

            </tr>
        </ng-template>
        <ng-template pTemplate="body" let-student let-columns="columns">
            <tr class="center-text">
                <td class="row-cell">{{student.name}}</td>
                <td class="row-cell">
                    {{student.email}}
                </td>

                <td class="row-cell">{{student.grades[0].grade1}}</td>

            </tr>
        </ng-template>
    </p-table>

</div>

If I enter any value present in the grade column,I get empty response. I think there's some issue with using grades[0].grade1 as field.

JSON Structure:

[
    {
        "name": "Test",
        "email": null,
        "phnNumber": 1,
        "grades": [
            {
                "grade1": "A",
                "grade2": "B"
            }
        ]
    }
]

Stackblitz- https://stackblitz.com/edit/angular-dbwfep


回答1:


You can use name[0].grade as filed property in column configuration. It can be any nested object. Filter is working.

The fact is that data on the table should the same property.

Update: You have to implement custom sorting and filter method of the table. Sorting is dynamic, as we know on which filed user want to sort based on click event, identifying the key is easy. But in the filter we don't know, the filter works for all the fields, so I have taken the 'grade1' field as of now to filter, you can add as many as field and remove after the filter.

I guess in case of a nested object, it doesn't work default, so you have to add custom implementation. Hope this helps.

component.html

<hello name="{{ title }}"></hello>
<div class="col-md-6">
    <p-table [columns]="cols" #dt [value]="students" [autoLayout]="true" [paginator]="true" [rows]="10" (onSort)="onSort($event)">
        <ng-template pTemplate="caption">
            <div style="text-align: right">
                <i class="fa fa-search" style="margin:4px 4px 0 0"></i>
                <input type="text" pInputText size="30" placeholder="Search" (input)="myFilter($event)" class="filter">
            </div>
        </ng-template>
        <ng-template pTemplate="header" let-columns>
            <tr>
                <th class="row-header" *ngFor="let col of columns" [pSortableColumn]="col.field">
                    {{col.header}}
                    <p-sortIcon class="" [field]="col.field" ariaLabel="Activate to sort" ariaLabelDesc="Activate to sort in descending order" ariaLabelAsc="Activate to sort in ascending order">
                    </p-sortIcon>
                </th>

            </tr>
        </ng-template>
        <ng-template pTemplate="body" let-student let-columns="columns">
            <tr class="center-text">
                <td class="row-cell">{{student.name}}</td>
                <td class="row-cell">
                    {{student.email}}
                </td>
                <td class="row-cell">
                    {{student.phnNumber}}
                </td>
                <td class="row-cell">{{student.grades[0].grade1}}</td>

            </tr>
        </ng-template>
    </p-table>

</div>

component.ts

import { FormControl, FormGroup } from "@angular/forms";
import { Component,
         ViewChild,
         AfterViewInit,
         ElementRef } from '@angular/core';
@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  title = "Filter in Table";
  cols = [];
  grades = [{ grade1: "grade1", grade2: "grade2" }];
  students = [];
  @ViewChild('dt',{read: '',static:true}) dt: any;

  constructor() {
    this.cols = [
      { field: "name", header: "Name" },
      { field: "email", header: "Email" },
      { field: "phnNumber", header: "Contact No" },
      { field: this.grades[0]["grade1"], header: "Grade1" }
    ];
    this.students = [
      {
        name: "Abhinav",
        email: "abhinavkumar985@gmail.com",
        phnNumber: "23456787654",
        grades: [
          {
            grade1: "AA",
            grade2: "X"
          }
        ]
      },
      {
        name: "Ravi",
        email: "Ravi@gmail.com",
        phnNumber: "1234543666",
        grades: [
          {
            grade1: "CC",
            grade2: "Y"
          }
        ]
      },
      {
        name: "Harsh",
        email: "hardss@gmail.com",
        phnNumber: "23212324",
        grades: [
          {
            grade1: "BB",
            grade2: "Z"
          }
        ]
      }
    ];
  }
  myFilter(e){
    this.dt.value.forEach((e)=>{
      e['grade1'] = e['grades'][0]['grade1'];
    });
    this.dt.filterGlobal(e.target.value, 'contains');
    setTimeout(()=>{
      this.dt.value.forEach((e)=>{
      delete e['grade1'];
    });
    },500)
  }
  onSort(e){
    let filed = e.field;
    let arr = [...this.students];
    if(filed === 'grade1'){
      // custome sort only for these fields

      let order = e.order; // 1 means abc and -1 means cba
      if(order === 1){
        this.students.sort( this.OrderListBy(filed) );
      }else{
        this.students.sort( this.OrderListBy(filed) ).reverse();
      }
    }
  }
  OrderListBy(prop) {
    return function (a, b) {
        if (a['grades'][0][prop] > b['grades'][0][prop]) {
            return 1;
        }
        else if (a['grades'][0][prop] < b['grades'][0][prop]) {
            return -1;
        }
        return 0;
    }
  }
}

see updated working example



来源:https://stackoverflow.com/questions/58851195/primeng-table-filter-not-working-on-column-with-nested-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!