How to apply filters to *ngFor?

前端 未结 23 1279
無奈伤痛
無奈伤痛 2020-11-22 03:44

Apparently, Angular 2 will use pipes instead of filters as in Angular1 in conjunction with ng-for to filter results, although the implementation still seems to be vague, wit

相关标签:
23条回答
  • 2020-11-22 03:53

    A lot of you have great approaches, but the goal here is to be generic and defined a array pipe that is extremely reusable across all cases in relationship to *ngFor.

    callback.pipe.ts (don't forget to add this to your module's declaration array)

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

    Then in your component, you need to implement a method with the following signuature (item: any) => boolean, in my case for example, I called it filterUser, that filters users' age that are greater than 18 years.

    Your Component

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

    And last but not least, your html code will look like this:

    Your HTML

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

    As you can see, this Pipe is fairly generic across all array like items that need to be filter via a callback. In mycase, I found it to be very useful for *ngFor like scenarios.

    Hope this helps!!!

    codematrix

    0 讨论(0)
  • 2020-11-22 03:55

    Basically, you write a pipe which you can then use in the *ngFor directive.

    In your component:

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

    In your template, you can pass string, number or object to your pipe to use to filter on:

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

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

    Remember to register your pipe in app.module.ts; you no longer need to register the pipes in your @Component

    import { MyFilterPipe } from './shared/pipes/my-filter.pipe';
    
    @NgModule({
        imports: [
            ..
        ],
        declarations: [
            MyFilterPipe,
        ],
        providers: [
            ..
        ],
        bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    Here's a Plunker which demos the use of a custom filter pipe and the built-in slice pipe to limit results.

    Please note (as several commentators have pointed out) that there is a reason why there are no built-in filter pipes in Angular.

    0 讨论(0)
  • 2020-11-22 03:55

    I'm not sure when it came in but they already made slice pipe that will do that. It's well documented too.

    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>
    
    0 讨论(0)
  • 2020-11-22 03:59

    Pipe would be best approach. but below one would also work.

    <div *ng-for="#item of itemsList">
      <ng-container *ng-if="conditon(item)">
        // my code
      </ng-container>
    </div>
    
    0 讨论(0)
  • 2020-11-22 04:02

    pipes in Angular2 are similar to pipes on the command line. The output of each preceding value is fed into the filter after the pipe which makes it easy to chain filters as well like this:

    <template *ngFor="#item of itemsList">
        <div *ngIf="conditon(item)">{item | filter1 | filter2}</div>
    </template>
    
    0 讨论(0)
  • 2020-11-22 04:04

    Based on the very elegant callback pipe solution proposed above, it is possible to generalize it a bit further by allowing additional filter parameters to be passed along. We then have :

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

    component

    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 讨论(0)
提交回复
热议问题