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

Writing a custom table filter in Angular 6

我想在我的 angular 代码中添加自定义 table 过滤器。网络搜索并找到了这个博客 post:

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] == "";
          });
        });
      }
    }
  }
}

除了这个 table 之外,它可以很好地满足我的大部分需求 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>

上面table的问题就是这个。要显示位置的站点名称,我使用此 html ...

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

... 它调用方法 getSiteName,该方法采用站点的 id 和站点名称 returns。我不知道如何设置我的 gridFilter。因此,如果我尝试搜索网站名称,我的 gridFilter 找不到该网站。

这是我的 stackblitz:https://stackblitz.com/edit/angular-damcul

** UPDATE **

我已经更新了我的 stackblitz to actually illustrate the problem I am having. Here is a screen shot of the stackblitz 应用程序:

我可以搜索位置,这是我搜索 'loc_2':

的屏幕截图

但是我无法搜索网站。这是我搜索任何 'site'.

的屏幕截图

进行了一些更改:

  • 在问题的共享代码中,您使用了名为 grdFilter 的过滤器,在您的 stackblitz 中它是 'gridFilter'
  • 添加了 getSiteName 的实现,它接收对象和 returns 博客名称(我们的数据中没有名为 '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;
  }
}

update #1 in light of questioner's comment & updated question:

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

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

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也更新了