Boosman
Boosman

Reputation: 197

Angular 2: Filter by value in nested array?

I’ve been experimenting with this GitHub repo via a course on Lynda.com (https://github.com/planetoftheweb/learnangular) by Ray Villalobos -- it functions similarly to a basic web app that I’m hoping to build, but I’ve recently hit a bit of a road block.

In that repo linked above, in app/component.app.ts, is the following array:

var ARTISTS: Artist[] = [
  {
    "name": "Barot Bellingham",
    "shortname": "Barot_Bellingham",
    "reknown": "Royal Academy of Painting and Sculpture",
    "bio": "Some bio here."
  },
  // etc...
]

This array is filtered by a pipe as seen in app/pipe.search.ts:

export class SearchPipe implements PipeTransform {
  transform(pipeData, pipeModifier) {
    return pipeData.filter((eachItem) => {
      return eachItem['name'].toLowerCase().includes(pipeModifier.toLowerCase()) ||
        eachItem['reknown'].toLowerCase().includes(pipeModifier.toLowerCase());
    });
  }
}

Here's the filter input:

<input class="search-input" [(ngModel)]="field1Filter" placeholder="type in search term here" (click)="showArtist(item); field1Filter=''">

And the code for the filter results:

<ul class="artistlist cf" *ngIf="field1Filter">
  <li class="artistlist-item cf"
     (click)="showArtist(item);"
     *ngFor="let item of (artists | search: field1Filter)"> 
    <artist-item class="content" [artist]=item></artist-item>
  </li>
</ul>
<artist-details  *ngIf="currentArtist" [artist]="currentArtist"></artist-details>

This all works perfectly, however, in my project, I would need to include three nested arrays, and have the ability to filter based upon the values in those arrays. A sample of the kind of array I need will look something like this:

var ARTISTS: Artist[] = [
  {
    "name": "Barot Bellingham",
    "shortname": "Barot_Bellingham",
    "reknown": "Royal Academy of Painting and Sculpture",
    "bio": "Some bio here...",
    "friends": [
      "James",
      "Harry",
      "Bob",
      "Liz",
      "Kate",
      "Jesse"
    ],
    "emails": [
      "[email protected]",
      "[email protected]"

    ],
    "car": [
      "honda",
      "scion",
      "aston martin"
    ]

  },
  // etc...
]

Therefore, I hope to filter by “Harry,” and only display objects that contain “harry” in either “name,” “reknown,” “friends,” "emails," or "cars." Is this possible, and if so, how can I edit the pipe filter to do this? Thank you!!

(I'm pretty green at angular and JS in general, so I want to apologize in advance if I’ve used incorrect terminology or overlooked/misunderstood something basic.)

Upvotes: 1

Views: 1745

Answers (1)

DeborahK
DeborahK

Reputation: 60626

I deleted my prior answer because it was more confusing than helpful. I pasted example code without applying it to your variables/properties/objects and it was misleading. Let's try again:

export class SearchPipe implements PipeTransform {
  transform(pipeData, pipeModifier) {
    pipeModifier = pipeModifier ? pipeModifier.toLowerCase() : null;
    return pipeModifier ? pipeData.filter(eachItem => {
      eachItem['name'].toLowerCase().indexOf(pipeModifier) !== -1 ||
      eachItem['reknown'].toLowerCase().indexOf(pipeModifier !== -1) : pipeData;
    });
  }
}

The first line of code in the transform method ensures that the modifier passed in is also lowercase so that the compare always compares lower case values. It also has a null check to ensure it does not try to lowercase it if it is null.

The second line of code also uses the "?" syntax to handle the case of a null pipeModifier.

I changed includes to indexOf. Includes checks arrays. Are these items, such as eachItem['name'], an array?

That should be closer.

NOTE: Without a provided plunker ... I did not check the syntax or correct execution of this code.

Upvotes: 2

Related Questions