Як застосувати фільтри до * ngFor?


278

Мабуть, Angular 2 використовуватиме труби замість фільтрів, як у Angular1 спільно з ng-for, щоб фільтрувати результати, хоча реалізація все ще видається невиразною, без чіткої документації.

А саме те, що я намагаюся досягти, можна розглядати з наступної точки зору

<div *ng-for="#item of itemsList" *ng-if="conditon(item)"></div>

Як здійснити так за допомогою труб?


8
Зауважте, що в бета-версії 17 для ngFor вводиться перемикача зміна щодо хеш-символу. Правильний шлях:<div *ngFor="let item of itemsList" *ngIf="conditon(item)" ...
Мемет Олсен


11
Коментар @MemetOlsen від Gunter нижче: " *ngForі *ngIfцей же елемент не підтримується. Вам потрібно перейти на явну форму для одного з них"
The Red Pea

1
Навіть тому, про що вимагає ОП, рекомендується НЕ ВИКОРИСТОВАТИ ПІПЕ для фільтрації чи замовлення в Angular2 +. Віддайте перевагу властивості класу з відфільтрованими значеннями: angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe
ylerjen

Відповіді:


395

В основному ви пишете трубу, яку потім можете використовувати в *ngForдирективі.

У вашому компоненті:

filterargs = {title: 'hello'};
items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];

У вашому шаблоні ви можете передати рядок, номер або об’єкт у вашу трубу, яку використовувати для фільтрації:

<li *ngFor="let item of items | myfilter:filterargs">

У вашій трубі:

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

@Pipe({
    name: 'myfilter',
    pure: false
})
export class MyFilterPipe implements PipeTransform {
    transform(items: any[], filter: Object): any {
        if (!items || !filter) {
            return items;
        }
        // filter items array, items which match and return true will be
        // kept, false will be filtered out
        return items.filter(item => item.title.indexOf(filter.title) !== -1);
    }
}

Не забудьте зареєструвати вашу трубу app.module.ts; вам більше не потрібно реєструвати труби у вашому@Component

import { MyFilterPipe } from './shared/pipes/my-filter.pipe';

@NgModule({
    imports: [
        ..
    ],
    declarations: [
        MyFilterPipe,
    ],
    providers: [
        ..
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

Ось Plunker, який демонструє використання спеціальної фільтрувальної труби та вбудованої трубочки для зрізів для обмеження результатів.

Зверніть увагу (як зазначили кілька коментаторів), що є причина, чому немає вбудованих фільтр-труб у Angular.


6
Дякую, це робота за призначенням, але іноді краще перевірити, чи визначено масив елементів, а не нуль, оскільки Ng2 може спробувати застосувати фільтр, поки "елементи" ще не визначені.
timmz

1
Крім того, мені потрібно було додати клас фільтру до декларації @Component. Як і ось: @Component ({... pipe: [MyFilterPipe]
Stephen

1
Я думаю, що він також потребує цього рядка "f (! Items) повертає елементи; "у випадку, якщо масив порожній.
Боштьян Пішлер

2
Кутовий говорить, що використання трубопроводу має проблеми, тому рекомендує зробити фільтрацію за компонентом
Sebastián Rojas

3
Я хотів би запропонувати зафіксувати *ngForпараметри в дужках, просто щоб уникнути плутанини і зробити це "стійким до змін":<li *ngFor="let item of (items | myfilter:filterargs)">
Томаш,

104

Багато з вас мають чудові підходи, але мета тут - бути загальним і визначати масив масиву, який надзвичайно багаторазовий для використання у всіх випадках стосовно * ngFor.

callback.pipe.ts (не забудьте додати це до масиву декларацій вашого модуля)

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

@Pipe({
    name: 'callback',
    pure: false
})
export class CallbackPipe implements PipeTransform {
    transform(items: any[], callback: (item: any) => boolean): any {
        if (!items || !callback) {
            return items;
        }
        return items.filter(item => callback(item));
    }
}

Тоді у своєму компоненті потрібно реалізувати метод із наступною ознакою (item: any) => boolean , у моєму випадку, наприклад, я назвав його filterUser, який фільтрує вік користувачів, який перевищує 18 років.

Ваш компонент

@Component({
  ....
})
export class UsersComponent {
  filterUser(user: IUser) {
    return !user.age >= 18
  }
}

І останнє, але не менш важливо, ваш html-код буде виглядати приблизно так:

Ваш HTML

<li *ngFor="let user of users | callback: filterUser">{{user.name}}</li>

Як бачите, ця труба є досить загальною для всіх масивів, як елементів, які потрібно фільтрувати за допомогою зворотного дзвінка. В моєму випадку я виявив, що це дуже корисно для подібних сценаріїв * ng.

Сподіваюся, це допомагає !!!

кодематриця


4
Я зауважую, що у функції filterUser () - або моїй еквівалентній функції цій - ви не можете використовувати "це" для доступу до поточного екземпляра компонента, як ви можете, з усіма іншими функціями класу компонентів. Мені потрібно звернутися до компонентного об’єкта, щоб перевірити, чи відфільтрований елемент знаходиться у колекції.
Поль

1
@Paul, хм ... це неможливо. Ваш метод приватний? Це не має значення, оскільки приватні особи - це лише компілюючі конструкції і не виконуються під час виконання. У своєму прикладі я використовував IUser. Це передбачає, що елементи колекції переглянуті до неї. Ви можете спробувати будь-який, щоб побачити, чи працює він. Також переконайтеся, що ім’я введено правильним, регістром та всім іншим.
код5

1
Я не можу
змінити

10
Щоб уникнути thisневизначеності, ви можете написати свій метод на своєму компоненті, filterUser = (user: IUser) =>а не наfilteruser(user: IUser)
Том,

2
@Paul Я знаю, що це занадто пізно, щоб допомогти вам, але це може допомогти іншим. Причина, яку ви втратили thisна своєму компонентному методі, полягає в тому, що метод використовувався як зворотний виклик і застосовано новий thisконтекст. Ви зіткнулися з поширеною проблемою в об'єктно-орієнтованому JavaScript, але є старе і просте рішення: ви прив'язуєте методи, що використовуються як зворотні дзвінки, до початкового класу. Додайте у свій конструктор наступний код: this.myCallbackFunc = this.myCallbackFunc.bind(this); Це все. Ви ніколи більше не втратите this.
Рандольфо

36

Спрощений спосіб (використовується лише для малих масивів через проблеми з продуктивністю. У великих масивах вам доведеться зробити фільтр вручну за допомогою коду):

Дивіться: https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe

@Pipe({
    name: 'filter'
})
@Injectable()
export class FilterPipe implements PipeTransform {
    transform(items: any[], field : string, value : string): any[] {  
      if (!items) return [];
      if (!value || value.length == 0) return items;
      return items.filter(it => 
      it[field].toLowerCase().indexOf(value.toLowerCase()) !=-1);
    }
}

Використання:

<li *ngFor="let it of its | filter : 'name' : 'value or variable'">{{it}}</li>

Якщо ви використовуєте змінну як другий аргумент, не використовуйте лапки.


3
Можливо, додайте наступне, щоб показати, як поєднати його з ReqExp: return items.filter (item => {return new RegExp (значення, "i"). Test (item [field])});
Йоганнес

8
За словами команди Angular, це вважається поганою практикою.

@torazaburo Ви можете посилатися на їхню думку чи пояснити чому? Спасибі
Zymotik

1
@Zymotik Дивіться angular.io/docs/ts/latest/guide/… .

2
За даними команди Angular, це поганий код, оскільки він повільний, і він не мінімізується добре. Команда не хоче бачити повільні веб-сайти через свій код, тому цього разу вони не вбудували її в Angular. angular.io/docs/ts/latest/guide/…
Зимотик

29

Це те, що я реалізував, не використовуючи трубу.

компонент.html

<div *ngFor="let item of filter(itemsList)">

компонент.ц

@Component({
....
})
export class YourComponent {
  filter(itemList: yourItemType[]): yourItemType[] {
    let result: yourItemType[] = [];
    //your filter logic here
    ...
    ...
    return result;
  }
}

16
Я думаю, що це було б обчислювально інтенсивним, оскільки Angular буде виконувати фільтр кожного разу, коли він запускає виявлення змін. Це не буде добре масштабувати великі масиви. Очищувач, хоча і більш складний для коду, рішення буде зробити itemListспостерігається і використовувати асинхронну фільтр: let item of itemsList | async. Коли відбудеться зміна, зробіть спостережуваний випуск нового списку. Таким чином, код фільтрації запускається лише за потреби.
BeetleJuice

1
Ця відповідь повинна мати негативну оцінку. Це погано, використовуйте трубу.
Сетія

19

Я не впевнений, коли він увійшов, але вони вже зробили зріз труби, який це зробить. Це теж добре задокументовано.

https://angular.io/docs/ts/latest/api/common/index/SlicePipe-pipe.html

<p *ngFor="let feature of content?.keyFeatures | slice:1:5">
   {{ feature.description }}
</p>

4
Якщо ви використовуєте інтерфейс trackBy, труба зрізу повинна застосовуватися перед ;. напр .:*ngFor="let feature of content?.keyFeatures | slice:1:5; trackBy feature?.id"
Філіп

11

Ви також можете скористатися наступним:

<template ngFor let-item [ngForOf]="itemsList">
    <div *ng-if="conditon(item)"></div>
</template>

Це покаже діг лише тоді, коли ваші предмети відповідають умові

Додаткову інформацію див. У кутовій документації. Якщо вам також знадобиться індекс, скористайтеся наступним:

<template ngFor let-item [ngForOf]="itemsList" let-i="index">
    <div *ng-if="conditon(item, i)"></div>
</template>

1
Чи не введеться це шаблон для кожного елемента у списку замість лише відфільтрованого списку? Це може бути хітом вистави.
Azeroth2b

8

Труби в Angular2 схожі на труби в командному рядку. Вихід кожного попереднього значення подається у фільтр після труби, що полегшує ланцюг фільтрів, як це:

<template *ngFor="#item of itemsList">
    <div *ngIf="conditon(item)">{item | filter1 | filter2}</div>
</template>

Вибачте, якщо це вводило в оману, мою думку тут є змінна itemвід, яку *ng-for="#item of itemsList"слід використовувати для фільтрації результатів як такої *ng-if="conditon(item)". Що не працює в цьому прикладі ..
Халед

ви можете зробити умову фільтром і зробити те ж саме з {{item | умова}} умова просто повернеться, itemякщо умова виконана, а значення немає, якщо її немає.
Бен Глассер

@BenGlasser Я думав, що труби застосовуються справа наліво. Таким чином, це застосує спочатку filter2, потім filter1.
Еван Плейс

12
*ngForі *ngIfна одному елементі не підтримуються. Вам потрібно змінити чітку форму для однієї з них<template ngFor ...>
Günter Zöchbauer

1
@ GünterZöchbauer У мене знадобився рік, але я оновив синтаксис, щоб відобразити запропоновані вами зміни
Бен Глассер

5

Для цієї вимоги я реалізую і публікую загальний компонент . Побачити

https://www.npmjs.com/package/w-ng5

Щоб використовувати ці компоненти, перед цим встановіть цей пакет із npm:

npm install w-ng5 --save

Після цього імпортуйте модуль у app.module

...
import { PipesModule } from 'w-ng5';

На наступному кроці додайте в декларацію розділ app.module:

imports: [
  PipesModule,
  ...
]

Використання зразків

Фільтрування простого рядка

<input type="text"  [(ngModel)]="filtroString">
<ul>
  <li *ngFor="let s of getStrings() | filter:filtroString">
    {{s}}
  </li>
</ul>

Фільтрація складного рядка - поле "Значення" на рівні 2

<input type="text"  [(ngModel)]="search">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.n2.valor2', value: search}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

Фільтрація складного рядка - середнє поле - "Значення" в рівні 1

<input type="text"  [(ngModel)]="search3">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.valor1', value: search3}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

Фільтрування складного масиву просто - поле 'Nome' рівень 0

<input type="text"  [(ngModel)]="search2">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'nome', value: search2}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

Фільтрування в полях дерев - поле "доблесть" на рівні 2 або "доблесть" на рівні 1 або "ном" на рівні 0

<input type="text"  [(ngModel)]="search5">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.n2.valor2', value: search5}, {field:'n1.valor1', value: search5}, {field:'nome', value: search5}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

Фільтрування неіснуючого поля - "доблесть" в неіснуючому рівні 3

<input type="text"  [(ngModel)]="search4">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.n2.n3.valor3', value: search4}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

Цей компонент працює з нескінченним рівнем атрибутів ...


Привіт, я тут, і я виконала всі кроки, і в цьому випадку я використовую це, *ngFor="let inovice of invoices | filter:searchInvoice"і він шукає в моєму списку, але показує порожній список, знаєте чому?
jecorrales

1
Привіт, скажіть, будь ласка, яка структура та тип об’єктів, що містяться у вашому списку рахунків-фактур. Спосіб, яким ви користуєтесь ним, слід застосовувати лише у тому випадку, якщо список ваших рахунків-фактур має рядковий тип. Якщо ви хочете здійснити пошук за номером рахунка-фактури (accountice.number), використовуйте це: * ngFor = "дозволити введення рахунків-фактур | filter: {field: number, value: searchInvoice}" . Якщо ви хочете фільтрувати за двома стовпцями, наприклад, accountice.customer.name, використовуйте: * ngFor = "дозволити інвойс рахунків-фактур | фільтр: [поле: номер, значення: searchInvoice}, {поле: ім'я клієнта, значення: searchInvoice}] .
Wedson Quintanilha da Silva

4

Просте рішення, яке працює з Angular 6 для фільтрації ngFor, це наступне:

<span *ngFor="item of itemsList"  >
  <div *ngIf="yourCondition(item)">
    
    your code
    
  </div>
</span

Проміжки корисні, тому що по суті нічого не представляють.


1
краще, ніж <span> - використовувати <ng-container>, оскільки це не додасть зайвої розмітки, яка крім html-шуму може вплинути на ваш CSS.
Тревор де Коеккьок

4

Я знаю, що це старе питання, однак я подумав, що може бути корисно запропонувати інше рішення.

еквівалент AngularJS цього

<div *ng-for="#item of itemsList" *ng-if="conditon(item)"></div>

у Angular 2+ ви не можете використовувати * ngFor і * ngIf для одного елемента, тож буде наступним:

<div *ngFor="let item of itemsList">
     <div *ngIf="conditon(item)">
     </div>
</div>

і якщо ви не можете використовувати як внутрішній контейнер, використовуйте натомість ng-контейнер. ng-контейнер корисний, коли ви хочете умовно додати групу елементів (тобто, використовуючи * ngIf = "foo") у вашій програмі, але не хочете обернути їх іншим елементом.


4

Я створив плунжер на основі відповідей тут і деінде.

Крім того , я повинен був додати @Input, @ViewChildі ElementRefз <input>а також створювати іsubscribe() до спостережуваних його.

Angular2 Фільтр пошуку: PLUNKR (ОНОВЛЕННЯ: планк більше не працює)


3

Труба була б найкращим підходом. але нижче один також буде працювати.

<div *ng-for="#item of itemsList">
  <ng-container *ng-if="conditon(item)">
    // my code
  </ng-container>
</div>

це може порушити певні речі. наприклад, усередині матового поля
pcnate

2

Це мій код:

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

@Pipe({
    name: 'filter'
})
@Injectable()
export class FilterPipe implements PipeTransform {
    transform(items: any[], field : string, value): any[] {
      if (!items) return [];
      if (!value || value.length === 0) return items;
      return items.filter(it =>
      it[field] === value);
    }
}

Зразок:

LIST = [{id:1,name:'abc'},{id:2,name:'cba'}];
FilterValue = 1;

<span *ngFor="let listItem of LIST | filter : 'id' : FilterValue">
                              {{listItem .name}}
                          </span>

1

Ще один підхід, який я люблю використовувати для спеціальних фільтрів додатків, - це використовувати власні властивості лише для читання на своєму компоненті, що дозволяє інкапсулювати логіку фільтрування більш чисто, ніж використання спеціальної труби (IMHO).

Наприклад, якщо я хочу прив’язати albumListта фільтрувати searchText:

searchText: "";
albumList: Album[] = [];

get filteredAlbumList() {
    if (this.config.searchText && this.config.searchText.length > 1) {
      var lsearchText = this.config.searchText.toLowerCase();
      return this.albumList.filter((a) =>
        a.Title.toLowerCase().includes(lsearchText) ||
        a.Artist.ArtistName.toLowerCase().includes(lsearchText)
      );
    }
    return this.albumList;
}

Щоб прив'язати HTML, ви можете прив'язати до властивості лише для читання:

<a class="list-group-item"
       *ngFor="let album of filteredAlbumList">
</a>

Я вважаю, що для спеціалізованих фільтрів, що стосуються конкретного застосування, це працює краще, ніж труба, оскільки він зберігає логіку, пов’язану з фільтром із компонентом.

Труби краще працюють для глобально використовуваних фільтрів.


1
Чи не призведе цей метод безперервні брудні перевірки замість використання підходу valueChanged?
Леон Пелтьє

1

Я створив наступну трубку для отримання потрібних елементів зі списку.

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

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {

  transform(items: any[], filter: string): any {
    if(!items || !filter) {
      return items;
    }
    // To search values only of "name" variable of your object(item)
    //return items.filter(item => item.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1);

    // To search in values of every variable of your object(item)
    return items.filter(item => JSON.stringify(item).toLowerCase().indexOf(filter.toLowerCase()) !== -1);
  }

}

Перетворення в малі регістри - це просто відповідати випадку нечутливого. Ви можете використовувати його у своєму поданні так: -

<div>
  <input type="text" placeholder="Search reward" [(ngModel)]="searchTerm">
</div>
<div>
  <ul>
    <li *ngFor="let reward of rewardList | filter:searchTerm">
      <div>
        <img [src]="reward.imageUrl"/>
        <p>{{reward.name}}</p>
      </div>
    </li>
  </ul>
</div>

1

В ідеалі для цього слід створити трубу angualr 2. Але ви можете зробити цю хитрість.

<ng-container *ngFor="item in itemsList">
    <div*ngIf="conditon(item)">{{item}}</div>
</ng-container>

1

На основі дуже елегантного рішення труб для зворотного виклику, запропонованого вище, можна узагальнити його трохи далі, дозволяючи передавати додаткові параметри фільтра. Потім у нас є:

callback.pipe.ts

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

@Pipe({
  name: 'callback',
  pure: false
})
export class CallbackPipe implements PipeTransform {
  transform(items: any[], callback: (item: any, callbackArgs?: any[]) => boolean, callbackArgs?: any[]): any {
    if (!items || !callback) {
      return items;
    }
    return items.filter(item => callback(item, callbackArgs));
  }
}

компонент

filterSomething(something: Something, filterArgs: any[]) {
  const firstArg = filterArgs[0];
  const secondArg = filterArgs[1];
  ...
  return <some condition based on something, firstArg, secondArg, etc.>;
}

html

<li *ngFor="let s of somethings | callback : filterSomething : [<whatWillBecomeFirstArg>, <whatWillBecomeSecondArg>, ...]">
  {{s.aProperty}}
</li>

0

Ось приклад того, що я створив деякий час назад, і про що вела блог, що включає в себе робочу планку. Він забезпечує фільтруючу трубу, яка може фільтрувати будь-який список об'єктів. Ви в основному просто вказуєте властивість та значення {key: value} у вашій специфікації ng.

Це не сильно відрізняється від відповіді @ NateMay, за винятком того, що я пояснюю це досить детально.

У моєму випадку я відфільтрував не упорядкований список на якомусь тексті (filterText), який користувач ввів проти властивості "label" об'єктів у моєму масиві таким чином розмітки:

<ul>
  <li *ngFor="let item of _items | filter:{label: filterText}">{{ item.label }}</li>
</ul>

https://long2know.com/2016/11/angular2-filter-pipes/


0

Перший крок ви створюєте за допомогою фільтра @Pipe у вашому файлі компонент.ts:

your.component.ts

import { Component, Pipe, PipeTransform, Injectable } from '@angular/core';
import { Person} from "yourPath";

@Pipe({
  name: 'searchfilter'
})
@Injectable()
export class SearchFilterPipe implements PipeTransform {
  transform(items: Person[], value: string): any[] {
    if (!items || !value) {
      return items;
    }
    console.log("your search token = "+value);
    return items.filter(e => e.firstName.toLowerCase().includes(value.toLocaleLowerCase()));
  }
}
@Component({
  ....
    persons;

    ngOnInit() {
         //inicial persons arrays
    }
})

І структура даних об'єкта Person:

person.ts

export class Person{
    constructor(
        public firstName: string,
        public lastName: string
    ) { }
}

На ваш погляд у html-файлі:

your.component.html

    <input class="form-control" placeholder="Search" id="search" type="text" [(ngModel)]="searchText"/>
    <table class="table table-striped table-hover">
      <colgroup>
        <col span="1" style="width: 50%;">
        <col span="1" style="width: 50%;">
      </colgroup>
      <thead>
        <tr>
          <th>First name</th>
          <th>Last name</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let person of persons | searchfilter:searchText">
          <td>{{person.firstName}}</td>
          <td>{{person.lastName}}</td>
        </tr>
      </tbody>
    </table>

0

Це ваш масив

products: any = [
        {
            "name": "John-Cena",
                    },
        {
            "name": "Brock-Lensar",

        }
    ];

Це ваш цикл ngFor Фільтр за:

<input type="text" [(ngModel)]='filterText' />
    <ul *ngFor='let product of filterProduct'>
      <li>{{product.name }}</li>
    </ul>

Там я використовую filterProduct миттєві продукти, тому що я хочу зберегти свої вихідні дані. Тут модель _filterText використовується як поле введення. Коли коли-небудь є функція встановлення змін, зателефонує. У setFilterText називається performProduct, він поверне результат лише тим, хто відповідає вводу. Я використовую малі регістри для нечутливих до регістру.

filterProduct = this.products;
_filterText : string;
    get filterText() : string {
        return this._filterText;
    }

    set filterText(value : string) {
        this._filterText = value;
        this.filterProduct = this._filterText ? this.performProduct(this._filterText) : this.products;

    } 

    performProduct(value : string ) : any {
            value = value.toLocaleLowerCase();
            return this.products.filter(( products : any ) => 
                products.name.toLocaleLowerCase().indexOf(value) !== -1);
        }

0

Після деякого гуглання я натрапив ng2-search-filter. In візьме ваш об’єкт і застосує пошуковий термін до всіх властивостей об'єкта, які шукають відповідність.


0

Я знаходив щось, щоб зробити фільтр, що передає Об'єкт, тоді я можу використовувати його як мультифільтр: Приклад мультифільтру

я зробив це рішення краси:

filter.pipe.ts

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

@Pipe({
  name: 'filterx',
  pure: false
})
export class FilterPipe implements PipeTransform {
 transform(items: any, filter: any, isAnd: boolean): any {
  let filterx=JSON.parse(JSON.stringify(filter));
  for (var prop in filterx) {
    if (Object.prototype.hasOwnProperty.call(filterx, prop)) {
       if(filterx[prop]=='')
       {
         delete filterx[prop];
       }
    }
 }
if (!items || !filterx) {
  return items;
}

return items.filter(function(obj) {
  return Object.keys(filterx).every(function(c) {
    return obj[c].toLowerCase().indexOf(filterx[c].toLowerCase()) !== -1
  });
  });
  }
}

компонент.ц

slotFilter:any={start:'',practitionerCodeDisplay:'',practitionerName:''};

componet.html

             <tr>
                <th class="text-center">  <input type="text" [(ngModel)]="slotFilter.start"></th>
                <th class="text-center"><input type="text" [(ngModel)]="slotFilter.practitionerCodeDisplay"></th>
                <th class="text-left"><input type="text" [(ngModel)]="slotFilter.practitionerName"></th>
                <th></th>
              </tr>


 <tbody *ngFor="let item of practionerRoleList | filterx: slotFilter">...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.