Jak zastosować filtry do * ngFor?


278

Najwyraźniej Angular 2 użyje potoków zamiast filtrów jak w Angular1 w połączeniu z ng-for do filtrowania wyników, chociaż implementacja nadal wydaje się niejasna, bez jasnej dokumentacji.

Mianowicie to, co próbuję osiągnąć, można zobaczyć z następującej perspektywy

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

Jak wdrożyć to za pomocą rur?


8
Zauważ, że przełomowa zmiana została wprowadzona w wersji beta 17 dla ngFor w odniesieniu do symbolu skrótu. Prawidłowy sposób to:<div *ngFor="let item of itemsList" *ngIf="conditon(item)" ...
Memet Olsen


11
@MemetOlsen komentarz od Guntera poniżej: „ *ngFori *ngIfna ten sam element nie są obsługiwane. Musisz zmienić jawny formularz dla jednego z nich”
The Red Pea

1
Nawet jeśli jest to, o co prosi OP, zaleca się NIE UŻYWAĆ PIPE do filtrowania lub zamawiania w Angular2 +. Wolę mieć właściwość klasy z filtrowanymi wartościami: angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe
ylerjen

Odpowiedzi:


395

Zasadniczo piszesz potok, którego możesz użyć w *ngFordyrektywie.

W twoim komponencie:

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

W szablonie możesz przekazać ciąg, numer lub obiekt do potoku, aby użyć go do filtrowania:

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

W twojej fajce:

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);
    }
}

Pamiętaj, aby zarejestrować swoją rurę app.module.ts; nie musisz już rejestrować rur w swoim@Component

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

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

Oto Plunker, który demonstruje użycie niestandardowej rury filtrującej i wbudowanej rury plastra, aby ograniczyć wyniki.

Należy pamiętać (jak zauważyło kilku komentatorów), że istnieje powód, dla którego nie ma wbudowanych rur filtrujących w Angular.


6
Dzięki, działa to zgodnie z przeznaczeniem, ale czasem lepiej jest sprawdzić, czy tablica elementów jest zdefiniowana, a nie zerowa, ponieważ Ng2 może próbować zastosować filtr, gdy „elementy” są jeszcze niezdefiniowane.
timmz

1
Ponadto musiałem dodać klasę filtra do deklaracji @Component. Like So: @Component ({... pipes: [MyFilterPipe]
Stephen

1
Myślę, że potrzebuje również tego wiersza ìf (! Items) return items; `w przypadku, gdy tablica jest pusta.
Boštjan Pišler,

2
Kątowe mówi użyciem Pipe wykonywania problemy, więc zaleca się, aby filtrowanie komponentu
Sebastián Rojas

3
Chciałbym zasugerować zawijanie *ngForparametrów w nawiasach, aby uniknąć nieporozumień i uczynić je „odpornymi na zmiany”:<li *ngFor="let item of (items | myfilter:filterargs)">
Tomas

104

Wielu z was ma świetne podejście, ale celem jest tutaj ogólne określenie i zdefiniowanie potoku tablicowego, który jest niezwykle wielokrotnego użytku we wszystkich przypadkach w odniesieniu do * ngFor.

callback.pipe.ts (nie zapomnij dodać tego do tablicy deklaracji modułu)

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));
    }
}

Następnie w swoim komponencie musisz zaimplementować metodę o następującej sygnaturze (item: any) => boolean , w moim przypadku na przykład nazwałem ją filterUser, który filtruje wiek użytkowników większy niż 18 lat.

Twój komponent

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

I na koniec, twój kod HTML będzie wyglądał następująco:

Twój HTML

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

Jak widać, ta rura jest dość ogólna dla wszystkich elementów podobnych do tablicy, które muszą być filtrowane przez wywołanie zwrotne. W przypadku mycase okazało się, że jest bardzo przydatny w przypadku * ngF w podobnych scenariuszach.

Mam nadzieję że to pomoże!!!

kodematrix


4
Zauważam, że w funkcji filterUser () - lub mojej równoważnej funkcji - nie można użyć „this”, aby uzyskać dostęp do bieżącej instancji komponentu, tak jak można to zrobić ze wszystkimi innymi funkcjami w klasie komponentów. Potrzebuję uzyskać dostęp do obiektu komponentu, aby sprawdzić, czy filtrowany element znajduje się w kolekcji.
Paul

1
@Paul, hmm ... to niemożliwe. Czy twoja metoda jest prywatna? Nie powinno to mieć znaczenia, ponieważ prywatne są tylko kompilacjami i nie są wymuszane w czasie wykonywania. W moim przykładzie użyłem IUser. Zakłada się, że elementy w kolekcji są iterowane na mapie. Możesz spróbować sprawdzić, czy to działa. Upewnij się także, że nazwa jest wpisana poprawnie, wielkość liter i wszystko.
code5

1
Nie mogę uzyskać dostępu do zmiennej komponentowej przy użyciu tej metody
suulisin 15.01.2018

10
Aby uniknąć problemu thisniezdefiniowania, możesz napisać metodę na swoim komponencie, filterUser = (user: IUser) =>a niefilteruser(user: IUser)
Tom

2
@Paul Wiem, że jest już za późno, aby ci pomóc, ale może pomóc innym. Przyczyną utraty thismetody komponentu jest to, że metoda była używana jako wywołanie zwrotne i zastosowano nowy thiskontekst. Wystąpił typowy problem w obiektowym javascript, ale istnieje stare i łatwe rozwiązanie: wiążesz metody, które mają być używane jako wywołania zwrotne do oryginalnej klasy. W swoim konstruktorze dodaj następujący kod: this.myCallbackFunc = this.myCallbackFunc.bind(this); To wszystko. Nigdy więcej nie stracisz this.
Randolpho,

36

Uproszczony sposób (używany tylko na małych tablicach z powodu problemów z wydajnością. W dużych tablicach filtr należy wykonać ręcznie za pomocą kodu):

Zobacz: 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);
    }
}

Stosowanie:

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

Jeśli użyjesz zmiennej jako drugiego argumentu, nie używaj cudzysłowów.


3
Może dodaj następujące, aby pokazać, jak połączyć to z ReqExp: return items.filter (item => {return new RegExp (wartość, „i”). Test (item [pole])});
Johannes

8
Według zespołu Angular jest to uważane za złą praktykę.

@torazaburo, czy możesz odnieść się do ich opinii lub wyjaśnić dlaczego? Dzięki
Zymotik


2
Według zespołu Angular jest to kiepski kod, ponieważ jest powolny i nie jest dobrze zminimalizowany. Zespół nie chce widzieć powolnych witryn ze względu na swój kod, więc tym razem nie wbudował go w Angular. angular.io/docs/ts/latest/guide/…
Zymotik

29

To właśnie zaimplementowałem bez użycia potoku.

component.html

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

component.ts

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

16
Myślę, że byłoby to intensywne obliczeniowo, ponieważ Angular wykona filtr za każdym razem, gdy uruchomi wykrywanie zmian. Nie będzie dobrze skalować do dużych tablic. Czystsze, choć bardziej skomplikowane do kodu, rozwiązaniem byłoby, aby itemListzauważalny i użyć filtru asynchronicznej: let item of itemsList | async. Gdy nastąpi zmiana, spraw, aby obserwowalne wyemitowały nową listę. W ten sposób kod filtrujący jest uruchamiany tylko w razie potrzeby.
BeetleJuice

1
Ta odpowiedź powinna mieć wynik negatywny. Źle, użyj fajki.
Cétia

19

Nie jestem pewien, kiedy to się pojawiło, ale już zrobili kromkę, która to zrobi. Jest również dobrze udokumentowany.

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
Jeśli korzystasz z interfejsu trackBy, rurka wycinająca musi zostać zastosowana przed ;. np:*ngFor="let feature of content?.keyFeatures | slice:1:5; trackBy feature?.id"
Philip

11

Możesz także użyć następujących:

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

To pokaże div, tylko jeśli twoje przedmioty spełniają warunek

Aby uzyskać więcej informacji, zobacz dokumentację kątową. Jeśli potrzebujesz również indeksu, skorzystaj z następujących opcji:

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

1
Czy to nie wprowadzi szablonu dla każdego elementu na liście zamiast tylko listy filtrowanej? To może być hit wydajności.
Azeroth2b,

8

potoki w Angular2 są podobne do potoków w wierszu polecenia. Wyjście każdej poprzedniej wartości jest podawane do filtra za rurą, co ułatwia łańcuch filtrów, jak to poniżej:

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

Przepraszam, jeśli to było mylące, moja uwaga tutaj to zmienna itemz *ng-for="#item of itemsList"powinna być używana do filtrowania wyników jako takich *ng-if="conditon(item)". Co nie działa w tym przykładzie ..
Khaled

możesz ustawić warunek jako filtr i zrobić to samo z {{item | warunek}} warunek po prostu zwróci, itemjeśli warunek zostanie spełniony, a jeśli nie, nie będzie żadnej wartości.
Ben Glasser,

@BenGlasser Myślałem, że rury były stosowane od prawej do lewej. Tak więc najpierw zastosuje filter2, a następnie filter1.
Evan Plaice,

12
*ngFori *ngIfna tym samym elemencie nie są obsługiwane. Musisz zmienić jawny formularz dla jednego z nich<template ngFor ...>
Günter Zöchbauer

1
@ GünterZöchbauer Zajęło mi to rok, ale zaktualizowałem składnię, aby odzwierciedlić zaproponowane zmiany
Ben Glasser

5

Dla tego wymagania wdrażam i publikuję ogólny komponent . Widzieć

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

Aby korzystać z tych komponentów, wcześniej zainstaluj ten pakiet z npm:

npm install w-ng5 --save

Następnie zaimportuj moduł do app.module

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

W następnym kroku dodaj sekcję deklarowania app.module:

imports: [
  PipesModule,
  ...
]

Przykładowe użycie

Filtrowanie prostego ciągu

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

Filtrowanie złożonego ciągu - pole „Wartość” na poziomie 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>

Filtrowanie łańcucha złożonego - pole środkowe - „Wartość” na poziomie 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>

Proste filtrowanie złożonej tablicy - pole „Nome” poziom 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>

Filtrowanie w polach drzewa - pole „Waleczność” na poziomie 2 lub „Waleczność” na poziomie 1 lub „Nome” na poziomie 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>

Filtrowanie nieistniejącego pola - „Waleczność” na nieistniejącym poziomie 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>

Ten komponent działa z nieskończonym poziomem atrybutu ...


Cześć, jestem tutaj i wykonałem wszystkie kroki. W tym przypadku korzystam z tego, *ngFor="let inovice of invoices | filter:searchInvoice"a on szuka na mojej liście, ale pokazuje pustą listę, wiesz dlaczego?
jecorrales

1
Witaj, proszę powiedz mi, jaka jest struktura i rodzaj obiektów, które zawiera twoja lista faktur. Sposób korzystania z niego powinien być stosowany tylko wtedy, gdy lista faktur jest typu ciąg. Jeśli chcesz wyszukiwać według numeru faktury (numer faktury), użyj tego: * ngFor = "pozwól na faktury | filtruj: {pole: liczba, wartość: faktura wyszukiwania}" . Jeśli chcesz filtrować według dwóch kolumn, na przykład faktury.nazwa.nazwa, użyj: * ngFor = "pozwól na fakturę | filtruj: [pole: liczba, wartość: faktura wyszukiwania}, {pole: nazwa.klienta, wartość: searchInvoice}] .
Wedson Quintanilha da Silva

4

Proste rozwiązanie współpracujące z Angular 6 do filtrowania ngFor jest następujące:

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

Rozpiętości są użyteczne, ponieważ z natury niczego nie reprezentują.


1
lepiej niż <span> jest użyć <ng-container>, ponieważ nie doda żadnych niepotrzebnych znaczników, które oprócz szumu HTML mogą wpływać na twój CSS.
Trevor de Koekkoek

4

Wiem, że to stare pytanie, ale pomyślałem, że może być pomocne zaproponowanie innego rozwiązania.

odpowiednik AngularJS tego

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

w Angular 2+ nie możesz używać * ngFor i * ngIf na tym samym elemencie, więc będzie on następujący:

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

a jeśli nie możesz użyć jako kontenera wewnętrznego, użyj zamiast tego ng-container. ng-container jest przydatny, gdy chcesz warunkowo dołączyć grupę elementów (tj. używając * ngIf = „foo”) w aplikacji, ale nie chcesz owijać ich innym elementem.


4

Stworzyłem plunker na podstawie odpowiedzi tu i gdzie indziej.

Dodatkowo musiałem dodaj @Input, @ViewChildoraz ElementRefz <input>oraz tworzenie i subscribe()do zauważalny od niego.

Filtr wyszukiwania Angular2: PLUNKR (AKTUALIZACJA: plunker już nie działa)


3

Najlepszym podejściem byłaby rura. ale poniżej jeden też by działał.

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

to może zepsuć pewne rzeczy. na przykład wewnątrz mat-Form-polowej
pcnate

2

To jest mój kod:

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);
    }
}

Próba:

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

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

1

Innym podejściem, które lubię stosować w przypadku filtrów specyficznych dla aplikacji, jest użycie niestandardowej właściwości tylko do odczytu w komponencie, która pozwala na bardziej przejrzystą enkapsulację logiki filtrowania niż przy użyciu niestandardowej potoku (IMHO).

Na przykład, jeśli chcę się połączyć albumListi filtrować 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;
}

Aby powiązać w kodzie HTML, możesz następnie powiązać właściwość tylko do odczytu:

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

Uważam, że dla wyspecjalizowanych filtrów specyficznych dla aplikacji działa to lepiej niż potok, ponieważ utrzymuje logikę związaną z filtrem ze składnikiem.

Rury działają lepiej w przypadku filtrów wielokrotnego użytku na całym świecie.


1
Czy ta metoda nie wyzwala ciągłego brudnego sprawdzania zamiast używania metody valueChanged?
Léon Pelletier,

1

Utworzyłem następujący potok, aby uzyskać pożądane elementy z listy.

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);
  }

}

Konwersja małych liter jest po prostu dopasowana w sposób bez rozróżniania wielkości liter. Możesz go użyć w swoim widoku w następujący sposób: -

<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

Idealnie powinieneś stworzyć do tego rurkę angualr 2. Ale możesz zrobić tę sztuczkę.

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

1

W oparciu o zaproponowane powyżej bardzo eleganckie rozwiązanie potoku zwrotnego możliwe jest jego dalsze uogólnienie, umożliwiając przekazanie dodatkowych parametrów filtra. Następnie mamy:

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));
  }
}

składnik

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

Oto przykład, który stworzyłem jakiś czas temu i napisałem na blogu, który zawiera działającą działkę. Zapewnia rurkę filtrującą, która może filtrować dowolną listę obiektów. Zasadniczo wystarczy podać właściwość i wartość {klucz: wartość} w specyfikacji ngFor.

Nie różni się niczym od odpowiedzi @ NateMay, tyle że wyjaśniam to dość szczegółowo.

W moim przypadku odfiltrowałem nieuporządkowaną listę na niektórych tekstach (filterText) wprowadzonych przez użytkownika względem właściwości „label” obiektów w mojej tablicy za pomocą tego rodzaju narzutów:

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

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


0

Pierwszym krokiem, w którym utworzysz filtr przy użyciu @Pipepliku component.ts:

twój.komponent.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
    }
})

I struktura danych obiektu Person:

person.ts

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

W twoim widoku w pliku HTML:

twój.komponent.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

To twoja tablica

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

        }
    ];

To jest twoja pętla ngFor Filtruj według:

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

Tam używam instant filterProduct produktów, ponieważ chcę zachować moje oryginalne dane. Tutaj model _filterText służy jako pole wprowadzania danych. Gdy tylko pojawi się jakakolwiek zmiana, zadzwoni funkcja ustawiająca. W setFilterText wywoływane jest performProduct, zwróci wynik tylko tym, którzy pasują do danych wejściowych. Używam małych liter, aby nie rozróżniać wielkich i małych liter.

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

Po pewnym googlowaniu natknąłem się ng2-search-filter. W zabierze obiekt i zastosuje wyszukiwane hasło do wszystkich właściwości obiektu szukających dopasowania.


0

Znalazłem coś dla zrobienia filtru przechodzącego przez obiekt, a potem mogę go użyć jak filtru wielofiltrowego: Przykład wielu filtrów

Zrobiłem to rozwiązanie kosmetyczne:

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
  });
  });
  }
}

component.ts

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

componentet.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">...
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.