Wie wende ich Filter auf * ngFor an?


278

Anscheinend wird Angular 2 Pipes anstelle von Filtern wie in Angular1 in Verbindung mit ng-for verwenden, um Ergebnisse zu filtern, obwohl die Implementierung noch vage zu sein scheint, ohne klare Dokumentation.

Was ich erreichen möchte, kann nämlich aus der folgenden Perspektive betrachtet werden

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

Wie implementiere ich das mit Rohren?


8
Beachten Sie, dass in Beta 17 für ngFor eine wichtige Änderung bezüglich des Hash-Symbols eingeführt wird. Der richtige Weg ist:<div *ngFor="let item of itemsList" *ngIf="conditon(item)" ...
Memet Olsen


11
@MemetOlsen Kommentar von Gunter unten: " *ngForund *ngIfauf dem gleichen Element werden nicht unterstützt. Sie müssen zu der expliziten Form für eines von ihnen wechseln"
The Red Pea

1
Auch wenn das OP dies verlangt, wird empfohlen, PIPE NICHT zum Filtern oder Bestellen in Angular2 + zu verwenden. Bevorzugen Sie eine Klasseneigenschaft mit den gefilterten Werten: angle.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe
ylerjen

Antworten:


395

Grundsätzlich schreiben Sie eine Pipe, die Sie dann in der *ngForDirektive verwenden können.

In Ihrer Komponente:

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

In Ihrer Vorlage können Sie eine Zeichenfolge, eine Nummer oder ein Objekt an Ihre Pipe übergeben, um nach folgenden Elementen zu filtern:

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

In deiner Pfeife:

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

Denken Sie daran, Ihre Pipe zu registrieren app.module.ts. Sie müssen die Rohre nicht mehr in Ihrem registrieren@Component

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

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

Hier ist ein Plunker, der die Verwendung eines benutzerdefinierten Filterrohrs und des integrierten Slice-Rohrs demonstriert , um die Ergebnisse zu begrenzen.

Bitte beachten Sie (wie mehrere Kommentatoren hervorgehoben haben), dass es einen Grund gibt, warum es in Angular keine eingebauten Filterrohre gibt.


6
Vielen Dank, dies funktioniert wie beabsichtigt, aber manchmal ist es besser zu überprüfen, ob das Elementarray definiert und nicht null ist, da Ng2 möglicherweise versucht, einen Filter anzuwenden, während die "Elemente" noch undefiniert sind.
Timmz

1
Außerdem musste ich die Filterklasse zur @ Component-Deklaration hinzufügen. Gefällt mir So: @Component ({... pipes: [MyFilterPipe]
Stephen

1
Ich denke, es braucht auch diese Zeile ìf (! Items) return items; `falls das Array leer ist.
Boštjan Pišler

2
Angular sagt, dass die Verwendung eines Rohrs Leistungsprobleme hat, und empfiehlt daher, die Komponente zu filtern
Sebastián Rojas

3
Ich möchte vorschlagen, *ngForParameter in Klammern zu setzen, um Verwirrung zu vermeiden und sie "veränderungssicher" zu machen:<li *ngFor="let item of (items | myfilter:filterargs)">
Tomas

104

Viele von Ihnen haben großartige Ansätze, aber das Ziel hier ist es, generisch zu sein und eine Array-Pipe zu definieren, die in Bezug auf * ngFor in allen Fällen extrem wiederverwendbar ist.

callback.pipe.ts (vergessen Sie nicht, dies dem Deklarationsarray Ihres Moduls hinzuzufügen)

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

Dann müssen Sie in Ihrer Komponente eine Methode mit der folgenden Signatur (item: any) => boolean implementieren. In meinem Fall habe ich sie beispielsweise filterUser genannt, um das Alter der Benutzer zu filtern, die größer als 18 Jahre sind.

Ihre Komponente

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

Und zu guter Letzt sieht Ihr HTML-Code folgendermaßen aus:

Ihr HTML

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

Wie Sie sehen können, ist diese Pipe für alle Array-ähnlichen Elemente, die über einen Rückruf gefiltert werden müssen, ziemlich allgemein. In meinem Fall fand ich es sehr nützlich für * ngFür ähnliche Szenarien.

Hoffe das hilft!!!

Codematrix


4
Ich stelle fest, dass Sie in der Funktion filterUser () - oder meiner entsprechenden Funktion - nicht "this" verwenden können, um wie bei allen anderen Funktionen in der Komponentenklasse auf die aktuelle Komponenteninstanz zuzugreifen. Ich muss auf das Komponentenobjekt zugreifen, um zu überprüfen, ob sich das gefilterte Element in einer Sammlung befindet.
Paul

1
@ Paul, hmm ... das ist unmöglich. Ist Ihre Methode privat? Nicht, dass dies von Bedeutung sein sollte, da Privates nur Kompilierungskonstrukte sind und zur Laufzeit nicht erzwungen werden. In meinem Beispiel habe ich IUser verwendet. Dies setzt voraus, dass die Elemente in der Sammlung, die iteriert werden, dieser zugeordnet sind. Sie können alle versuchen, um zu sehen, ob es funktioniert. Stellen Sie außerdem sicher, dass der Name korrekt eingegeben ist, Groß- und Kleinschreibung und alles.
Code5

1
Ich kann nicht auf Komponentenvariable mit dieser Methode
zugreifen

10
Um das Problem der thisfilterUser = (user: IUser) =>filteruser(user: IUser)
Tom

2
@ Paul Ich weiß, das ist zu spät, um dir zu helfen, aber es könnte anderen helfen. Der Grund, warum Sie thisbei Ihrer Komponentenmethode verloren haben, ist, dass die Methode als Rückruf verwendet wurde und ein neuer thisKontext angewendet wurde. Sie sind auf ein häufiges Problem in objektorientiertem Javascript gestoßen, aber es gibt eine alte und einfache Lösung: Sie binden Methoden, die als Rückrufe verwendet werden sollen, an die ursprüngliche Klasse. Fügen Sie in Ihrem Konstruktor den folgenden Code hinzu: this.myCallbackFunc = this.myCallbackFunc.bind(this); Das war's. Du wirst nie thiswieder verlieren .
Randolpho

36

Vereinfachte Methode (Wird aufgrund von Leistungsproblemen nur bei kleinen Arrays verwendet. Bei großen Arrays muss der Filter manuell per Code erstellt werden):

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

Verwendungszweck:

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

Wenn Sie eine Variable als zweites Argument verwenden, verwenden Sie keine Anführungszeichen.


3
Fügen Sie möglicherweise Folgendes hinzu, um zu zeigen, wie es mit ReqExp kombiniert werden kann: return items.filter (item => {neues RegExp zurückgeben (Wert, "i"). Test (item [Feld])});
Johannes

8
Laut dem Angular-Team gilt dies als schlechte Praxis.

@torazaburo können Sie ihre Meinung beziehen oder erklären, warum? Danke
Zymotik


2
Laut dem Angular-Team ist dies ein schlechter Code, da er langsam und nicht gut minimiert ist. Das Team möchte aufgrund seines Codes keine langsamen Websites sehen, daher haben sie es diesmal nicht in Angular integriert. angle.io/docs/ts/latest/guide/…
Zymotik

29

Dies ist, was ich ohne Verwendung von Pipe implementiert habe.

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
Ich denke, dies wäre rechenintensiv, da Angular den Filter jedes Mal ausführt, wenn eine Änderungserkennung ausgeführt wird. Es lässt sich nicht gut auf große Arrays skalieren. Eine sauberere, wenn auch komplexere Lösung für den Code wäre, itemListein Observable zu erstellen und den asynchronen Filter zu verwenden : let item of itemsList | async. Wenn eine Änderung auftritt, lassen Sie das Observable die neue Liste ausgeben. Auf diese Weise wird der Filtercode nur bei Bedarf ausgeführt.
BeetleJuice

1
Diese Antwort sollte eine negative Punktzahl haben. Es ist schlecht, benutze eine Pfeife.
Cétia

19

Ich bin mir nicht sicher, wann es reinkam, aber sie haben bereits Slice Pipe gemacht, das das macht. Es ist auch gut dokumentiert.

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
Wenn Sie das trackBy-Interface verwenden, muss das Slice-Pipe vor dem angewendet werden ;. zB:*ngFor="let feature of content?.keyFeatures | slice:1:5; trackBy feature?.id"
Philip

11

Sie können auch Folgendes verwenden:

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

Dies zeigt nur die Div an, wenn Ihre Artikel der Bedingung entsprechen

Siehe die Winkel Dokumentation für weitere Informationen Wenn Sie auch den Index benötigen würde, verwenden Sie die folgenden Schritte aus :

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

1
Wird nicht die Vorlage für jedes Element in der Liste anstelle nur der gefilterten Liste eingegeben? Das könnte ein Performance-Hit sein.
Azeroth2b

8

Pipes in Angular2 ähneln Pipes in der Befehlszeile. Die Ausgabe jedes vorhergehenden Werts wird nach dem Rohr in den Filter eingespeist, wodurch es einfach ist, Filter wie folgt zu verketten:

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

Entschuldigung, wenn dies irreführend war, mein Punkt hier ist, dass die Variable itemvon *ng-for="#item of itemsList"verwendet werden sollte, um die Ergebnisse als solche zu filtern *ng-if="conditon(item)". Was in diesem Beispiel nicht funktioniert ..
Khaled

Sie könnten Bedingung zu einem Filter machen und dasselbe mit {{item | tun Bedingung}} Bedingung würde nur zurückgeben, itemwenn die Bedingung erfüllt ist, und keinen Wert, wenn dies nicht der Fall ist.
Ben Glasser

@ BenGlasser Ich dachte, Rohre wurden von rechts nach links angewendet. Dies würde also zuerst Filter2 und dann Filter1 anwenden.
Evan Plaice

12
*ngForund *ngIfauf dem gleichen Element werden nicht unterstützt. Sie müssen zu der expliziten Form für einen von ihnen wechseln<template ngFor ...>
Günter Zöchbauer

1
@ GünterZöchbauer Ich habe ein Jahr gebraucht, aber ich habe die Syntax aktualisiert, um die von Ihnen vorgeschlagenen Änderungen widerzuspiegeln
Ben Glasser

5

Für diese Anforderung implementiere und veröffentliche ich eine generische Komponente . Sehen

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

Um diese Komponenten zu verwenden, installieren Sie dieses Paket zuvor mit npm:

npm install w-ng5 --save

Importieren Sie anschließend das Modul in app.module

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

Fügen Sie im nächsten Schritt den Deklarationsabschnitt von app.module hinzu:

imports: [
  PipesModule,
  ...
]

Verwendung der Probe

Einfache Zeichenfolge filtern

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

Filterung komplexer Zeichenfolgen - Feld 'Wert' in Ebene 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>

Filterung komplexer Zeichenfolgen - mittleres Feld - 'Wert' in Ebene 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>

Einfaches Filtern komplexer Arrays - Feld 'Nome' Level 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>

Filtern in Baumfeldern - Feld 'Tapferkeit' in Stufe 2 oder 'Tapferkeit' in Stufe 1 oder 'Nome' in Stufe 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>

Nicht vorhandenes Feld filtern - 'Tapferkeit' in nicht vorhandenem Level 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>

Diese Komponente arbeitet mit einer unendlichen Attributebene ...


Hallo, ich bin hier und habe alle Schritte befolgt. In diesem Fall verwende ich dies *ngFor="let inovice of invoices | filter:searchInvoice"und es wird auf meiner Liste gesucht, aber es wird eine leere Liste angezeigt. Weißt du warum?
Jecorrales

1
Hallo, bitte sagen Sie mir, welche Struktur und Art von Objekten Ihre Rechnungsliste enthält. Die Art und Weise, wie Sie es verwenden, sollte nur angewendet werden, wenn Ihre Rechnungsliste vom Typ Zeichenfolge ist. Wenn Sie nach Rechnungsnummer (rechnungsnummer) suchen möchten, verwenden Sie Folgendes : * ngFor = "Rechnung einlösen lassen | Filter: {Feld: Nummer, Wert: Suchrechnung}" . Wenn Sie nach zwei Spalten filtern möchten, z. B. Rechnung.Kundenname, verwenden Sie: * ngFor = "Rechnung einlösen lassen | Filter: [Feld: Nummer, Wert: Suchrechnung}, {Feld: Kundenname, Wert: searchInvoice}] .
Wedson Quintanilha da Silva

4

Eine einfache Lösung, die mit Angular 6 zum Filtern eines ngFor zusammenarbeitet, ist die folgende:

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

Spannweiten sind nützlich, da sie von Natur aus nichts darstellen.


1
Besser als <span> ist die Verwendung von <ng-container>, da keine unnötigen Markups hinzugefügt werden, die zusätzlich zum HTML-Rauschen Ihr CSS beeinträchtigen könnten.
Trevor de Koekkoek

4

Ich weiß, dass es eine alte Frage ist, aber ich dachte, es könnte hilfreich sein, eine andere Lösung anzubieten.

Äquivalent von AngularJS davon

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

In Angular 2+ können Sie * ngFor und * ngIf nicht für dasselbe Element verwenden.

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

und wenn Sie nicht als internen Container verwenden können, verwenden Sie stattdessen ng-container. ng-container ist nützlich, wenn Sie eine Gruppe von Elementen (dh mit * ngIf = "foo") in Ihrer Anwendung bedingt anhängen möchten, diese aber nicht mit einem anderen Element umschließen möchten.


4

Ich habe einen Plunker erstellt, der auf den Antworten hier und anderswo basiert.

Zusätzlich musste ich ein @Input, @ViewChildund ElementRefvon <input>und erstellen und subscribe()ein beobachtbares davon erstellen .

Angular2-Suchfilter: PLUNKR (UPDATE: Plunker funktioniert nicht mehr)


3

Rohr wäre der beste Ansatz. aber unten würde man auch funktionieren.

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

Dies kann bestimmte Dinge brechen. Zum Beispiel in einem Mat-Form-Feld
pcnate

2

Das ist mein 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);
    }
}

Stichprobe:

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

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

1

Ein anderer Ansatz, den ich gerne für anwendungsspezifische Filter verwende, ist die Verwendung einer benutzerdefinierten schreibgeschützten Eigenschaft für Ihre Komponente, mit der Sie die Filterlogik sauberer kapseln können als mit einer benutzerdefinierten Pipe (IMHO).

Zum Beispiel, wenn ich binden albumListund filtern möchte 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;
}

Um im HTML zu binden, können Sie dann an die schreibgeschützte Eigenschaft binden:

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

Ich finde, dass für spezielle Filter, die anwendungsspezifisch sind, dies besser funktioniert als eine Pipe, da die Logik in Bezug auf den Filter mit der Komponente beibehalten wird.

Rohre funktionieren besser für global wiederverwendbare Filter.


1
Wird diese Methode nicht kontinuierliche Dirty-Checks auslösen, anstatt einen valueChanged-Ansatz zu verwenden?
Léon Pelletier

1

Ich habe die folgende Pipe erstellt, um die gewünschten Elemente aus einer Liste abzurufen.

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

}

Die Konvertierung in Kleinbuchstaben entspricht nur der Groß- und Kleinschreibung. Sie können es in Ihrer Ansicht folgendermaßen verwenden: -

<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

Idealerweise sollten Sie dafür ein Angualr 2-Rohr erstellen. Aber du kannst diesen Trick machen.

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

1

Basierend auf der oben vorgeschlagenen sehr eleganten Callback-Pipe-Lösung ist es möglich, sie etwas weiter zu verallgemeinern, indem zusätzliche Filterparameter weitergegeben werden. Wir haben dann:

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

Komponente

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

Hier ist ein Beispiel, das ich vor einiger Zeit erstellt und über das ich gebloggt habe und das einen funktionierenden Plunk enthält. Es bietet eine Filterpipe, mit der jede Liste von Objekten gefiltert werden kann. Sie geben im Grunde nur die Eigenschaft und den Wert {key: value} in Ihrer ngFor-Spezifikation an.

Es unterscheidet sich nicht wesentlich von der Antwort von @ NateMay, außer dass ich es relativ ausführlich erkläre.

In meinem Fall habe ich eine ungeordnete Liste nach Text (filterText) gefiltert, den der Benutzer mit dieser Art von Markup gegen die Eigenschaft "label" der Objekte in meinem Array eingegeben hat:

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

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


0

Der erste Schritt, den Sie mit Filter @Pipein Ihrer Datei component.ts erstellen:

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

Und Datenstruktur des Personenobjekts:

person.ts

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

Aus Ihrer Sicht in einer HTML-Datei:

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

Dies ist Ihr Array

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

        }
    ];

Dies ist Ihre ngFor-Schleife. Filtern nach:

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

Dort verwende ich filterProduct Instant of Products, weil ich meine Originaldaten beibehalten möchte. Hier wird das Modell _filterText als Eingabefeld verwendet. Wann immer es eine Änderung gibt, wird die Setter-Funktion aufgerufen. In setFilterText wird performProduct aufgerufen, und es wird nur das Ergebnis zurückgegeben, das mit der Eingabe übereinstimmt. Ich verwende Kleinbuchstaben für Groß- und Kleinschreibung.

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

Nach einigem googeln bin ich rübergekommen ng2-search-filter. In nimmt Ihr Objekt und wendet den Suchbegriff auf alle Objekteigenschaften an, die nach einer Übereinstimmung suchen.


0

Ich habe etwas gefunden, um einen Filter zu erstellen, der ein Objekt passiert, dann kann ich ihn wie einen Mehrfachfilter verwenden: Beispiel für mehrere Filter

Ich habe diese Beauty-Lösung gemacht:

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">...
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.