在Angular 6中编写自定义表格过滤器

时间:2019-06-18 02:36:37

标签: html angular typescript angular-pipe

我想在我的角度代码中添加一个自定义表格过滤器。进行网络搜索并找到此博客文章:

https://www.code-sample.com/2018/07/angular-6-search-filter-pipe-table-by.html

效果很好,下面是管道代码:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'gridFilter'
})

/*
 I got this code from here:
 https://www.code-sample.com/2018/07/angular-6-search-filter-pipe-table-by.html
*/

export class GridFilterPipe implements PipeTransform {
  transform(items: any, filter: any, defaultFilter: boolean): any {
    if (!filter){
      return items;
    }

    if (!Array.isArray(items)){
      return items;
    }

    if (filter && Array.isArray(items)) {
      let filterKeys = Object.keys(filter);

      if (defaultFilter) {
        return items.filter(item =>
            filterKeys.reduce((x, keyName) =>
                (x && new RegExp(filter[keyName], 'gi').test(item[keyName])) || filter[keyName] == "", true));
      }
      else {
        return items.filter(item => {
          return filterKeys.some((keyName) => {
            return new RegExp(filter[keyName], 'gi').test(item[keyName]) || filter[keyName] == "";
          });
        });
      }
    }
  }
}

对于我的大多数需求,它都可以很好地工作,除了这张表是html:

  <div class="col-md-4" *ngIf="element == 'location'">
    <div class="spacer"></div>
    <div class="panel panel--vibblue panel--raised">{{ element | titlecase }}</div>
    <div class="responsive-table panel--raised">
      <table class="table table--bordered table--hover approvals-table" id="location-table">
        <thead>
        <tr>
          <th class="sortable">{{ element | titlecase }} Name <span class="sort-indicator icon-chevron-down"></span></th>
          <th class="sortable">Site <span class="sort-indicator icon-chevron-down"></span></th>
          <th>Action</th>
        </tr>
        </thead>
        <tbody>
        <ng-container *ngFor="let el of elements | gridFilter: {name: searchText, site:searchText}">
          <tr>
            <td>{{el.name}}</td>
            <td>{{ getSiteName(el.site) }}</td>
            <td>
              <a><span class="icon-trash" (click)="deleteElement(el.id, el.name)"></span></a>
            </td><td>
            <a><span class="icon-pencil" (click)="editElement(el)"></span></a>
          </td>
          </tr>
        </ng-container>
        </tbody>
      </table>
    </div>
  </div>

上表的问题是这个。要显示位置的站点名称,请使用此html ...

<td>{{ getSiteName(el.site) }}</td>

...调用方法getSiteName,该方法使用网站的id并返回网站的名称。我不知道如何设置我的gridFilter。因此,如果我尝试搜索站点名称,则gridFilter找不到该站点。

这是我对此的快速反应:https://stackblitz.com/edit/angular-damcul

  

**更新**

我已经更新了stackblitz,以实际说明我遇到的问题。这是stackblitz应用的屏幕截图:

enter image description here

我可以搜索位置,这是我搜索“ loc_2”的屏幕截图:

enter image description here

但是我无法搜索网站。这是我搜索任何“站点”的屏幕截图。

enter image description here

1 个答案:

答案 0 :(得分:2)

进行了一些更改:

  • 在问题的共享代码中,您使用了名为grdFilter的过滤器,在堆栈闪电中它是“ gridFilter”
  • 添加了getSiteName的实现,该实现接受对象并返回博客名称(我们的数据中没有名为“ site”的属性)
  • 在问题的共享代码中,您有

<ng-container *ngFor="let el of customerData | gridFilter: {name: searchText, site:searchText}">

  • 由于我们的数据中没有名为“ site”的属性,因此我们将其更改为

<ng-container *ngFor="let el of customerData | grdFilter: {name: searchText, blog:searchText}">

相关的 hello.componenet.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<input [(ngModel)]="searchText" placeholder="Search.." class="advancedSearchTextbox">
<p></p>
<table *ngFor="let emp of customerData | grdFilter: {name: searchText, Age:searchText,  blog: searchText}; let i=index;">
  <tr>
    <td style="width: 5%;">{{i +1}}</td>
    <td style="width: 10%;">{{emp.name}}</td>
    <td style="width: 5%;">{{emp.Age}}</td>
    <td style="width: 15%;">{{emp.blog}}</td>
  </tr>
</table>
<hr/>
<table class="table table--bordered table--hover approvals-table" id="location-table">
  <thead>
    <tr>
      <th class="sortable">{{ element | titlecase }} Name <span class="sort-indicator icon-chevron-down"></span></th>
      <th class="sortable">Site <span class="sort-indicator icon-chevron-down"></span></th>
      <th>Action</th>
    </tr>
  </thead>
  <tbody>
    <ng-container *ngFor="let el of customerData | grdFilter: {name: searchText, blog:searchText}">
      <tr>
        <td>{{el.name}}</td>
        <td>{{ getSiteName(el) }}</td>
        <td>
          <a><span class="icon-trash" (click)="deleteElement(el.id, el.name)"></span></a>
        </td><td>
        <a><span class="icon-pencil" (click)="editElement(el)"></span></a>
      </td>
      </tr>
    </ng-container>
  </tbody>
</table>
`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
  public searchText: string;
  public customerData: any;

  @Input() name: string;

  constructor() { }

  ngOnInit() {
    this.customerData = [
      { "name": 'Anil kumar', "Age": 34, "blog": 'https://code-view.com' },
      { "name": 'Sunil Kumar Singh', "Age": 28, "blog": 'https://code-sample.xyz' },
      { "name": 'Sushil Singh', "Age": 24, "blog": 'https://code-sample.com' },
      { "name": 'Aradhya Singh', "Age": 5, "blog": 'https://code-sample.com' },
      { "name": 'Reena Singh', "Age": 28, "blog": 'https://code-sample.com' },
      { "name": 'Alok Singh', "Age": 35, "blog": 'https://code-sample.com' },
      { "name": 'Dilip Singh', "Age": 34, "blog": 'https://code-sample.com' }];
  }
  getSiteName(passedObj) {
    return passedObj.blog;
  }
}
  

更新#1   鉴于提问者的评论和更新的问题:

如果转到grd-pipe.ts文件并执行console.log(items,filter),您会看到我们在自定义管道中处理的数组是locations数组,其中包含“ sites '列值为1、2或3。您从sites数组中为UI获取的站点名称不是locations数组的一部分,因此无法通过管道进行处理。

因此,我们在存储站点名称(从sites数组开始)的locations数组中创建了一个新字段siteName,由于该字段在管道内部可用,因此管道也可以在其上进行搜索。

TS

中的相关更改
ngOnInit(){
for(var i=0;i<this.locations.length;i++){
        this.locations[i].siteName = this.sites.find(s => s.id === this.locations[i].site).name;
      }
}

HTML 中的相关更改,已将添加的字段siteName添加到过滤器中:

<table class="table table--bordered table--hover approvals-table" id="location-table">
  <tbody>
    <ng-container *ngFor="let loc of locations | grdFilter: {name: searchText, siteName:searchText}; let i=index">
      <tr>
        <td style="width: 5%;">{{i +1}}</td>
        <td style="width: 10%;">{{loc.name}}</td>
        <td style="width: 5%;">{{getSiteName(loc.site)}}</td>
      </tr>
    </ng-container>
  </tbody>
</table>

工作stackblitz here也已更新