Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 3 how to filter array nested in 2 *ngFor?

Tags:

angular

ionic3

I would like to filter day.children name property based on search input. Having difficulties with that nested *ngFor because one relies on second. dayOverViewByGroup is comming from API. I tried to wrap day.children in a function like filterIt(day.children) but I got infinite loop. Thank you.

I have following(simplified) html structure

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

dayOverview variable example data from API

// 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": [

    ]
  }
]

like image 422
Verthon Avatar asked Dec 01 '25 03:12

Verthon


1 Answers

Add an Observable filteredChildren$ that emits the filtered children to your day objects.

To create filteredChildren$ you need an Observable of filter values. Add a FormControl to your search bar so you can listen to its value changes. (You have to import ReactiveFormsModule)

Demo (Angular 8, Ionic 4, RxJS 6)

Demo (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))
    );
  }
}
like image 156
frido Avatar answered Dec 02 '25 18:12

frido



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!