angular - איך ליישם פילטרים על *ngFor?


לכאורה, Angular 2 ישתמש בצינורות במקום מסננים כפי שנעשה ב-Angular1 בשילוב עם ng-for כדי לסנן תוצאות, למרות שהיישום עדיין נראה מעורפל, ללא תיעוד ברור.

כלומר, מה שאני מנסה להשיג ניתן לראות מנקודת המבט הבאה

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

איך לממש כך באמצעות צינורות?

תשובה #1

בעקרון, אתה כותב פייפ שאותו תוכל להשתמש בו לאחר מכן בהוראת *ngFor.

ברכיב שלך:

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

בתבנית שלך, אתה יכול להעביר מחרוזת, מספר או אובייקט לצינור שלך כדי להשתמש בו לסינון:

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

בטבעת הצינור שלך:

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

זכור לרשום את הפייפ שלך ב-app.module.ts; אין צורך יותר לרשום את הפייפים ב-@Component שלך

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

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

הנה Plunker שמדגים את השימוש בצנרת מסנן מותאמת אישית ובצנרת החיתוך המובנית להגבלת תוצאות.

שימו לב (כפי שמספר מפרשנים הצביעו) שיש סיבה לכך שאין מסנני צנורות מובנים ב-Angular.

תשובה #2

הרבה מכם יש גישות מצוינות, אבל המטרה כאן היא להיות כלליים ולהגדיר pipe של מערך שהוא קל לשימוש חוזר בכל המקרים בקשר ל-*ngFor.

callback.pipe.ts (אל תשכח להוסיף את זה למערך ההצהרות של המודול שלך)

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

אז ברכיב שלך, אתה צריך לממש שיטה עם החתימה הבאה (item: any) => boolean, במקרה שלי לדוגמה, קראתי לה filterUser, שמסננת את גיל המשתמשים שהם מעל 18 שנים.

הקומפוננטה שלך

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

ולסיום, אך לא פחות חשוב, קוד ה-HTML שלך ייראה כך:

ה-HTML שלך

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

כפי שאתה יכול לראות, צינור זה הוא די כללי לכל פריטים הדומים למערכים שצריכים להיות מסוננים דרך callback. במקרה שלי, מצאתי אותו שימושי מאוד לתרחישים דומים ל-*ngFor.

מקווה שזה עוזר!!!

קודמטריקס

תשובה #3

זו מה שמימשתי ללא שימוש בצנרת.

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

תשובה #4

דרך מפושטת (נעשה שימוש רק במערכים קטנים בגלל בעיות ביצועים. במערכים גדולים יש לבצע את הסינון ידנית באמצעות קוד):

ראה: 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);
    }
}

שימוש :

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

אם אתה משתמש במשתנה כארגומנט שני, אל תשתמש במרכאות.

תשובה #5

אני לא בטוח מתי זה הגיע אבל הם כבר ייצרו צינור פרוס שיכול לעשות את זה. זה מתועד היטב גם כן.

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>

תשובה #6

פתרון פשוט שעובד עם Angular 6 לסינון ngFor, זה הבא:

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

מרווחים שימושיים כי הם אינם מייצגים באופן טבעי שום דבר.

תשובה #7

אתה גם יכול להשתמש בזה:

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

זה יציג את ה-div רק אם הפריטים שלך עומדים בתנאי

עיין בתיעוד של Angular למידע נוסף. אם תזדקק גם לאינדקס, השתמש בבל הבא:

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