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>
