Написание пользовательского табличного фильтра на Angular 6 - PullRequest
2 голосов
/ 18 июня 2019

Я хотел добавить пользовательский табличный фильтр в мой угловой код.Сделал поиск в Интернете и нашел эту запись в блоге:

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 Ответ

2 голосов
/ 18 июня 2019

внесены некоторые изменения:

  • в вашем общем коде в вопросе вы использовали фильтр с именем grdFilter, в вашем стеке блиц это был 'gridFilter'
  • реализация *Добавлено 1007 *, которое принимает объект и возвращает имя блога (в наших данных нет свойства с именем 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), вы увидите, что массив, над которым мы работаем внутри пользовательского канала, является массивом местоположений, который имеет значения столбца 'sites'как 1, 2 или 3. Имя сайта, которое вы выбрали для пользовательского интерфейса из массива сайтов, не является частью массива местоположений и, следовательно, не может быть обработанопо каналу.

Итак, мы создаем новое поле 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>

работает стек * здесь также обновляется

...