Comment appliquer des filtres à * ngFor?

278

Apparemment, Angular 2 utilisera des tuyaux au lieu de filtres comme dans Angular1 en conjonction avec ng-for pour filtrer les résultats, bien que l'implémentation semble toujours vague, sans documentation claire.

À savoir ce que j'essaie de réaliser pourrait être considéré du point de vue suivant

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

Comment mettre en œuvre ainsi en utilisant des tuyaux?

Khaled
la source
8
Notez qu'un changement de rupture est introduit dans la bêta 17 pour ngFor concernant le symbole de hachage. La bonne façon est:<div *ngFor="let item of itemsList" *ngIf="conditon(item)" ...
Memet Olsen
11
Commentaire de @MemetOlsen de Gunter ci-dessous: " *ngForet *ngIfsur le même élément ne sont pas pris en charge. Vous devez modifier le formulaire explicite pour l'un d'eux"
The Red Pea
1
Même si c'est ce que l'OP demande, il est recommandé de NE PAS UTILISER DE TUYAU pour filtrer ou commander dans Angular2 +. Préférez avoir une propriété de classe avec les valeurs filtrées: angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe
ylerjen

Réponses:

395

Fondamentalement, vous écrivez un tube que vous pouvez ensuite utiliser dans la *ngFordirective.

Dans votre composant:

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

Dans votre modèle, vous pouvez passer une chaîne, un nombre ou un objet à votre pipe pour l'utiliser pour filtrer:

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

Dans votre pipe:

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

N'oubliez pas d'enregistrer votre pipe app.module.ts; vous n'avez plus besoin d'enregistrer les tuyaux dans votre@Component

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

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

Voici un plongeur qui l'utilisation d'un tuyau de filtre personnalisé et du tuyau de coupe intégré pour limiter les résultats.

Veuillez noter (comme plusieurs commentateurs l'ont souligné) qu'il y a une raison pour laquelle il n'y a pas de tuyaux de filtre intégrés dans Angular.

phuc77
la source
6
Merci, cela fonctionne comme prévu, mais il est parfois préférable de vérifier si le tableau des éléments est défini et non nul, car Ng2 peut essayer d'appliquer un filtre alors que les "éléments" ne sont toujours pas définis.
timmz
1
De plus, j'avais besoin d'ajouter la classe de filtre à la déclaration @Component. Comme ça: @Component ({... pipes: [MyFilterPipe]
Stephen
1
Je pense qu'il a également besoin de cette ligne "f (! Items) return items;" au cas où le tableau serait vide.
Boštjan Pišler
2
Angular dit que l'utilisation d'un tuyau présente des problèmes de performance, recommande donc de filtrer le composant
Sebastián Rojas
3
Je voudrais suggérer de mettre les *ngForparamètres entre parenthèses, juste pour éviter toute confusion et le rendre "à l'épreuve du changement":<li *ngFor="let item of (items | myfilter:filterargs)">
Tomas
104

Beaucoup d'entre vous ont d'excellentes approches, mais l'objectif ici est d'être générique et de définir un tube de tableau qui est extrêmement réutilisable dans tous les cas en relation avec * ngFor.

callback.pipe.ts (n'oubliez pas d'ajouter ceci au tableau de déclaration de votre module)

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

Ensuite, dans votre composant, vous devez implémenter une méthode avec la signature suivante (item: any) => booléen , dans mon cas par exemple, je l'ai appelé filterUser, qui filtre l'âge des utilisateurs supérieur à 18 ans.

Votre composant

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

Et enfin et surtout, votre code html ressemblera à ceci:

Votre HTML

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

Comme vous pouvez le voir, ce canal est assez générique sur tous les éléments de type tableau qui doivent être filtrés via un rappel. Dans mon cas, je l'ai trouvé très utile pour * ngFor comme des scénarios.

J'espère que cela t'aides!!!

codematrix

code5
la source
4
Je remarque que dans la fonction filterUser () - ou ma fonction équivalente à cela - vous ne pouvez pas utiliser "ceci" pour accéder à l'instance de composant actuelle comme vous pouvez le faire avec toutes les autres fonctions de la classe de composants. J'ai besoin d'accéder à l'objet composant pour vérifier que l'élément filtré se trouve dans une collection.
Paul
1
@Paul, hmm ... c'est impossible. Votre méthode est-elle privée? Cela ne devrait pas avoir d'importance car les fichiers privés ne sont que des constructions de compilation et ne sont pas appliqués lors de l'exécution. Dans mon exemple, j'ai utilisé IUser. Cela suppose que les éléments de la collection à itérer y sont mappés. Vous pouvez en essayer pour voir si cela fonctionne. Assurez-vous également que le nom est tapé correctement, casse et tout.
code5
1
je ne peux pas accéder à la variable du composant en utilisant cette méthode
suulisin
10
Pour éviter le problème d' thisêtre indéfini, vous pouvez écrire votre méthode sur votre composant comme filterUser = (user: IUser) =>plutôt quefilteruser(user: IUser)
Tom
2
@Paul Je sais que c'est trop tard pour vous aider, mais cela pourrait aider les autres. La raison pour laquelle vous perdiez thissur votre méthode de composant est que la méthode était utilisée comme rappel et qu'un nouveau thiscontexte a été appliqué. Vous avez rencontré un problème courant en javascript orienté objet, mais il existe une solution ancienne et simple: vous liez des méthodes à utiliser comme rappels à la classe d'origine. Dans votre constructeur, ajoutez le code suivant: this.myCallbackFunc = this.myCallbackFunc.bind(this); C'est tout. Vous ne perdrez thisplus jamais .
Randolpho
36

Manière simplifiée (utilisé uniquement sur les petits tableaux en raison de problèmes de performances. Dans les grands tableaux, vous devez effectuer le filtre manuellement via le code):

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

Usage:

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

Si vous utilisez une variable comme deuxième argument, n'utilisez pas de guillemets.

Rodolfo Jorge Nemer Nogueira
la source
3
Ajoutez peut-être ce qui suit pour montrer comment le combiner avec ReqExp: return items.filter (item => {return new RegExp (value, "i"). Test (item [field])});
Johannes
8
Selon l'équipe angulaire, cela est considéré comme une mauvaise pratique.
@torazaburo pouvez-vous faire référence à leur opinion ou expliquer pourquoi? Merci
Zymotik
2
Selon l'équipe Angular, c'est un mauvais code car il est lent et il n'est pas bien minimisé. L'équipe ne veut pas voir les sites Web lents en raison de leur code, ils ne l'ont donc pas intégré à Angular cette fois. angular.io/docs/ts/latest/guide/…
Zymotik
29

C'est ce que j'ai implémenté sans utiliser de pipe.

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;
  }
}
Thang Le
la source
16
Je pense que ce serait un calcul intensif car Angular exécutera le filtre à chaque fois qu'il exécute la détection de changement. Il ne s'adaptera pas bien aux grands tableaux. Un nettoyeur, bien que plus complexe à code, la solution serait de faire itemListun Observable et utiliser le filtre async: let item of itemsList | async. Lorsqu'un changement se produit, faites en sorte que l'observable émette la nouvelle liste. De cette façon, le code de filtrage n'est exécuté qu'en cas de besoin.
BeetleJuice
1
Cette réponse devrait avoir un score négatif. C'est mauvais, utilisez une pipe.
Cétia
19

Je ne sais pas quand il est arrivé, mais ils ont déjà fait un tuyau de tranche qui le fera. C'est aussi bien documenté.

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>
SpaceBeers
la source
4
Si vous utilisez l' interface trackBy, le tuyau de tranche doit être appliqué avant le ;. par exemple:*ngFor="let feature of content?.keyFeatures | slice:1:5; trackBy feature?.id"
Philip
11

Vous pouvez également utiliser les éléments suivants:

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

Cela ne montrera le div que si vos articles correspondent à la condition

Voir la documentation angulaire pour plus d'informations Si vous avez également besoin de l'index, utilisez ce qui suit:

<template ngFor let-item [ngForOf]="itemsList" let-i="index">
    <div *ng-if="conditon(item, i)"></div>
</template>
Jeroen
la source
1
Cela n'entrera-t-il pas dans le modèle de chaque élément de la liste au lieu de simplement la liste filtrée? Cela pourrait être un succès de performance.
Azeroth2b
8

les tuyaux dans Angular2 sont similaires aux tuyaux sur la ligne de commande. La sortie de chaque valeur précédente est introduite dans le filtre après le tuyau, ce qui facilite l'enchaînement des filtres ainsi:

<template *ngFor="#item of itemsList">
    <div *ngIf="conditon(item)">{item | filter1 | filter2}</div>
</template>
Ben Glasser
la source
Désolé si cela était trompeur, mon point ici est que la variable itemde *ng-for="#item of itemsList"devrait être utilisée pour filtrer les résultats en tant que tels *ng-if="conditon(item)". Ce qui ne fonctionne pas dans cet exemple ..
Khaled
vous pouvez faire de la condition un filtre et faire la même chose avec {{item | condition}} condition reviendrait simplement itemsi la condition est remplie et aucune valeur si elle ne l'est pas.
Ben Glasser
@BenGlasser Je pensais que les tuyaux étaient appliqués de droite à gauche. Donc, cela appliquerait filter2 d'abord, puis filter1.
Evan Plaice
12
*ngForet *ngIfsur le même élément ne sont pas pris en charge. Vous devez changer le formulaire explicite pour l'un d'eux<template ngFor ...>
Günter Zöchbauer
1
@ GünterZöchbauer Cela m'a pris un an, mais j'ai mis à jour la syntaxe pour refléter les changements que vous avez suggérés
Ben Glasser
5

Pour cette exigence, j'implémente et publie un composant générique . Voir

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

Pour utiliser ces composants, avant, installez ce package avec npm:

npm install w-ng5 --save

Après, importez le module dans app.module

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

À l'étape suivante, ajoutez la section declare de app.module:

imports: [
  PipesModule,
  ...
]

Exemple d'utilisation

Filtrage d'une chaîne simple

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

Filtrage d'une chaîne complexe - champ 'Valeur' ​​au niveau 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>

Filtrage d'une chaîne complexe - champ central - «Valeur» au niveau 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>

Filtrage d'un tableau complexe simple - champ 'Nome' niveau 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>

Filtrage dans les champs de l'arborescence - champ 'Valor' au niveau 2 ou 'Valor' au niveau 1 ou 'Nome' au niveau 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>

Filtrage d'un champ inexistant - «Valor» dans un niveau 3 inexistant

<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>

Ce composant fonctionne avec un niveau d'attribut infini ...

Wedson Quintanilha da Silva
la source
Salut, je suis ici et j'ai suivi toutes les étapes et dans ce cas, j'utilise ceci *ngFor="let inovice of invoices | filter:searchInvoice"et il recherche dans ma liste, mais affiche une liste vierge, savez-vous pourquoi?
jecorrales
1
Bonjour, dites-moi quelle est la structure et le type d'objets que contient votre liste de factures. La façon dont vous l'utilisez ne doit être appliquée que si votre liste de factures est de type chaîne. Si vous souhaitez effectuer une recherche par numéro de facture (facture.numéro), utilisez ceci: * ngFor = "laissez la facture des factures | filtrer: {champ: numéro, valeur: searchInvoice}" . Si vous souhaitez filtrer par deux colonnes, par exemple, facture.customer.name, utilisez: * ngFor = "laissez la facture des factures | filtre: [champ: numéro, valeur: searchInvoice}, {champ: client.nom, valeur: searchInvoice}] .
Wedson Quintanilha da Silva
4

Une solution simple qui fonctionne avec Angular 6 pour filtrer un ngFor, c'est la suivante:

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

Les portées sont utiles car elles ne représentent rien en soi.

Michael V
la source
1
mieux que <span> est d'utiliser <ng-container> car il n'ajoutera aucun balisage inutile qui, en plus du bruit html, pourrait affecter votre CSS.
Trevor de Koekkoek
4

Je sais que c'est une vieille question, cependant, j'ai pensé qu'il pourrait être utile de proposer une autre solution.

équivalent de AngularJS de cette

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

dans Angular 2+, vous ne pouvez pas utiliser * ngFor et * ngIf sur un même élément, il sera donc le suivant:

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

et si vous ne pouvez pas l'utiliser comme conteneur interne, utilisez plutôt ng-container. ng-container est utile lorsque vous souhaitez ajouter conditionnellement un groupe d'éléments (c'est-à-dire en utilisant * ngIf = "foo") dans votre application mais que vous ne voulez pas les encapsuler avec un autre élément.

tgralex
la source
4

J'ai créé un plongeur basé sur les réponses ici et ailleurs.

De plus , je devais ajouter un @Input, @ViewChildet ElementRefde <input>créer etsubscribe() à une observable de celui - ci.

Filtre de recherche Angular2: PLUNKR (MISE À JOUR: plunker ne fonctionne plus)

Nate May
la source
3

La pipe serait la meilleure approche. mais en dessous on fonctionnerait aussi.

<div *ng-for="#item of itemsList">
  <ng-container *ng-if="conditon(item)">
    // my code
  </ng-container>
</div>
Hardik Patel
la source
cela peut casser certaines choses. par exemple à l' intérieur d' un tapis en forme de champ
pcnate
2

Voici mon code:

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

Échantillon:

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

<span *ngFor="let listItem of LIST | filter : 'id' : FilterValue">
                              {{listItem .name}}
                          </span>
Pàldi Gergő
la source
1

Une autre approche que j'aime utiliser pour les filtres spécifiques à une application est d'utiliser une propriété en lecture seule personnalisée sur votre composant qui vous permet d'encapsuler la logique de filtrage plus proprement que d'utiliser un canal personnalisé (IMHO).

Par exemple, si je veux me lier à albumListet filtrer sur 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;
}

Pour lier dans le HTML, vous pouvez ensuite vous lier à la propriété en lecture seule:

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

Je trouve que pour les filtres spécialisés qui sont spécifiques à l'application, cela fonctionne mieux qu'un tuyau car il conserve la logique liée au filtre avec le composant.

Les tuyaux fonctionnent mieux pour les filtres réutilisables à l'échelle mondiale.

Rick Strahl
la source
1
Cette méthode ne déclenchera-t-elle pas des vérifications sales continues au lieu d'utiliser une approche valueChanged?
Léon Pelletier
1

J'ai créé le tube suivant pour obtenir les éléments souhaités d'une liste.

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

}

La conversion en minuscules est juste pour correspondre dans le cas insensible. Vous pouvez l'utiliser dans votre vue comme ceci: -

<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>
Sanchit Tandon
la source
1

Idéalement, vous devriez créer un tuyau angualr 2 pour cela. Mais vous pouvez faire cette astuce.

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

Sur la base de la solution de tuyau de rappel très élégante proposée ci-dessus, il est possible de le généraliser un peu plus en permettant le passage de paramètres de filtre supplémentaires. On a alors:

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

composant

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>
Blablalux
la source
0

Voici un exemple que j'ai créé il y a quelque temps et sur lequel j'ai blogué, qui comprend un plunk fonctionnel. Il fournit un tuyau de filtrage qui peut filtrer n'importe quelle liste d'objets. Vous spécifiez simplement la propriété et la valeur {key: value} dans votre spécification ngFor.

Ce n'est pas très différent de la réponse de @ NateMay, sauf que je l'explique de manière relativement détaillée.

Dans mon cas, j'ai filtré une liste non ordonnée sur du texte (filterText) que l'utilisateur a entré par rapport à la propriété "label" des objets de mon tableau avec ce type de balisage:

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

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

long2know
la source
0

La première étape que vous créez à l'aide de Filter @Pipedans votre fichier component.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
    }
})

Et la structure de données de l'objet Personne:

person.ts

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

Dans votre vue en fichier 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>
Piotr R
la source
0

Ceci est votre tableau

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

        }
    ];

Voici votre boucle ngFor Filtrer par:

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

Là, j'utilise filterProduct instant des produits, car je veux conserver mes données d'origine. Ici, le modèle _filterText est utilisé comme zone de saisie. Chaque fois qu'il y a une fonction de définition de changement, elle sera appelée. Dans setFilterText, performProduct est appelé, il ne retournera le résultat que ceux qui correspondent à l'entrée. J'utilise des minuscules pour insensible à la casse.

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);
        }
Gajender Singh
la source
0

Après quelques recherches sur Google, je suis tombé sur ng2-search-filter. Dans prendra votre objet et appliquera le terme de recherche à toutes les propriétés d'objet à la recherche d'une correspondance.

alindber
la source
0

Je trouvais quelque chose pour faire un filtre en passant un objet, alors je peux l'utiliser comme multi-filtre: Exemple de filtre multiple

j'ai fait cette solution de beauté:

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:''};

component.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">...
Richard Aguirre
la source