how to filter the list using pipes in angular 2

2019-07-29 17:17发布

问题:

could you please tell me how to filter the list using pipes in angular 2

https://stackblitz.com/edit/angular-qvtqeu?file=src%2Fapp%2Fapp.component.html

I tried like this

<ul class="user-list | filterlist:userenter">
  <li *ngFor="let user of users" class="user-list__item">

Filter

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

@Pipe({
  name: 'filterlist'
})
export class FilterlistPipe implements PipeTransform {

  transform(value: any, args?: any): any {
    return value.filter(
      item => item.first_name.toLowerCase().indexOf(args.toLowerCase()) > -1
   );
  }

}

But filtering is not working when I type on input field ?

回答1:

Working Demo

you should do like this

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

@Pipe({
  name: 'filterlist'
})
export class FilterlistPipe implements PipeTransform {

  transform(value: any, args?: any): any {
    if(!args)
     return value;
    return value.filter(
      item => item.first_name.toLowerCase().indexOf(args.toLowerCase()) > -1
   );
  }
}

check for args is having value or not , and first time you are not going to have value for args ..that is a reason its not working



回答2:

The reason Angular doesn't ship with pipes to do this, is because it will have terrible performance.

For every single row in your array, you will iterate the entire array. Repeat that possibly several times per second. This is not something you want.

Instead, declare your list like this:

allUsers: [];
filteredUsers: [];

Populate allUsers as you presently do users. Then, in every place searchText changes, iterate allUsers and add the matching users to filteredUsers. This way, if only five users match your search text, the template only needs to iterate five times.

Your loop becomes:

<ul class="user-list">
  <li *ngFor="let user of filteredUsers" class="user-list__item">
</ul>

And so on.

I should add that since I first posted this answer, I have also used the same technique whenever I wanted to reduce the amount of work done in my templates. I've found that having your template iterate only a thousand times can perform very poorly on older mobile devices and cause noticeable delays even on my beastly i7 development PC.



回答3:

Return all items if args is null.

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

 @Pipe({
  name: 'filterlist'
 })
 export class FilterlistPipe implements PipeTransform {

 transform(value: any, args?: any): any {
  // added code
  if(args == null){
    return value;
   }
 // added code

   return value.filter(
     item => item.first_name.toLowerCase().indexOf(args.toLowerCase()) > -1
  );
 }

}


回答4:

You can use ng2-search-filter npm.
For more details you can go through this demo: Demo Link

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

// search module
import { Ng2SearchPipeModule } from 'ng2-search-filter';

import { AppComponent } from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule, Ng2SearchPipeModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  title = 'Angular Search Using ng2-search-filter';
  searchText;
  heroes = [
    { id: 11, name: 'Mr. Nice', country: 'India' },
    { id: 12, name: 'Narco' , country: 'USA'},
    { id: 13, name: 'Bombasto' , country: 'UK'},
    { id: 14, name: 'Celeritas' , country: 'Canada'},
    { id: 15, name: 'Magneta' , country: 'Russia'},
    { id: 16, name: 'RubberMan' , country: 'China'},
    { id: 17, name: 'Dynama' , country: 'Germany'},
    { id: 18, name: 'Dr IQ' , country: 'Hong Kong'},
    { id: 19, name: 'Magma' , country: 'South Africa'},
    { id: 20, name: 'Tornado' , country: 'Sri Lanka'}
  ];
}

app.component.html

<div class="container text-center">
  <h1>{{title}}</h1>
</div>
<div class="container">
  <div class="row">
    <div class="search-hero">
      <input class="form-control" type="text" name="search" [(ngModel)]="searchText" autocomplete="off" placeholder="&#61442;  Start searching for a hero by id or name or country">
    </div>
    <table class="table table-striped">
      <thead>
      <tr>
        <th>Id</th>
        <th>Hero Name</th>
        <th>Country</th>
      </tr>
      </thead>
      <tbody>
      <tr *ngFor="let hero of heroes | filter:searchText">
        <td>{{hero.id}}</td>
        <td>{{hero.name}}</td>
        <td>{{hero.country}}</td>
      </tr>
      </tbody>
    </table>
  </div>
</div>

This will take care of filtering the data from the result list. Hope this will help you.



回答5:

You have applied the filter to the class attribute..

It should be in *ngFor:

*ngFor="let user of users | filterlist:userenter"

In your pipe code (filterlist.pipe.ts) return the whole array when there is no filter set:

if(args === undefined){
  return value;
}