首页 > 解决方案 > Ionic 3如何过滤嵌套在2 *ngFor中的数组?

问题描述

我想day.children name根据搜索输入过滤属性。嵌套 *ngFor 遇到困难,因为一个依赖于第二个。dayOverViewByGroup来自 API。我试图包装day.children一个类似的函数,filterIt(day.children)但我得到了无限循环。谢谢你。

我有以下(简化的)html结构

<ion-searchbar placeholder="Suchen..." (ionInput)="searchChildren($event)" padding></ion-searchbar>
<ion-grid *ngFor="let day of dayOverViewByGroup; let i = index" padding>
  <ion-card *ngFor="let child of day.children; let j = index">
  <h1>{{child.name}}</h1>
</ion-grid>

来自 API 的 dayOverview 变量示例数据

// dayOverview variable example data from API

[
  {
    "name": "Kindergarden 1",
    "presence_id": 25,
    "totalChildren": 3,
    "totalCheckinChildren": 1,
    "children": [
      {
        "name": "John Doe",
        "daycareComment": null,
        "parentComment": null,
        "id": "10633",
        "away": null,
        "checkin": [],
        "additionalDay": false,
        "remarks": "",
        "awayClass": "",
        "reason": "",
        "addtionalClass": "",
        "disableToggle": false,
        "disabled": false,
        "checkout": "Nicht anwesend",
        "class": "notcheckin"
      },
      {
        "name": "Jane Doe",
        "daycareComment": null,
        "parentComment": null,
        "id": "8322",
        "away": null,
        "checkin": [],
        "additionalDay": false,
        "remarks": "",
        "awayClass": "",
        "reason": "",
        "addtionalClass": "",
        "disableToggle": false,
        "disabled": false,
        "checkout": "Nicht anwesend",
        "class": "notcheckin"
      },
      {
        "name": "Bastian Paper",
        "daycareComment": null,
        "parentComment": null,
        "id": "86999",
        "away": null,
        "checkin": [],
        "additionalDay": false,
        "remarks": "",
        "awayClass": "",
        "reason": "",
        "addtionalClass": "",
        "disableToggle": false,
        "disabled": true,
        "class": "checkin",
        "checkout": "Anwesend"
      }
    ]
  },
  {
    "name": "Kindergarden 2",
    "presence_id": 26,
    "totalChildren": 1,
    "totalCheckinChildren": 0,
    "children": [
      {
        "name": "Thomas Mueller",
        "daycareComment": null,
        "parentComment": null,
        "id": "86900",
        "away": null,
        "checkin": [],
        "additionalDay": false,
        "remarks": "",
        "awayClass": "",
        "reason": "",
        "addtionalClass": "",
        "disableToggle": false,
        "disabled": false,
        "checkout": "Nicht anwesend",
        "class": "notcheckin"
      }
    ]
  },
  {
    "name": "Kindergarden 3",
    "presence_id": 27,
    "totalChildren": 1,
    "totalCheckinChildren": 0,
    "children": [

    ]
  }
]

标签: angularionic3

解决方案


添加一个可filteredChildren$将过滤后的子对象发送到day对象的 Observable。

要创建filteredChildren$您需要一个可观察的过滤器值。将 FormControl 添加到您的搜索栏,以便您可以收听其值的变化。(你必须导入ReactiveFormsModule

演示(Angular 8、Ionic 4、RxJS 6)

演示(Angular 5、Ionic 3、RxJS 5.5)

<ion-searchbar placeholder="Suchen..." [formControl]="filterControl" padding></ion-searchbar>
<ion-grid *ngFor="let day of dayOverViewByGroup$ | async; let i = index" padding>       
  <ion-card *ngFor="let child of day.filteredChildren$ | async; let j = index">
    <h1>{{child.name}}</h1>
  </ion-card>
</ion-grid>
export class Component {
  filterControl = new FormControl();
  dayOverViewByGroup$: Observable<any>

  ngOnInit() {
    const filter$: Observable<string> = this.filterControl.valueChanges.pipe(
      startWith(''),
      debounceTime(100), 
      distinctUntilChanged(),
      share() // we use filter$ multiple times so we share a single subscription to the source
    );
    this.dayOverViewByGroup$ = this.fetchData().pipe(
      map(days => days.map(day => (
        {
          ...day,
          // add an Observable that emits an array of filtered children
          filteredChildren$: filter$.pipe(this.filterFrom(day.children))
        }
      )))
    );
  }

  fetchData(): Observable<any[]> {
    // fetch data from Api
    return of(data);
  }

  filterFrom(children: { name: string }[]) {
    return (filter$: Observable<string>) => filter$.pipe(
      // the filter logic (add your own here)
      map(f => children.filter(child => child.name.toLowerCase().indexOf(f.toLowerCase()) > -1))
    );
  }
}

推荐阅读