Angular 8/9 | Custom Filter Pipe Get Child Values based on Parent Id Passed

In client-side applications, we may need to filter out a set of data based on some unique values of the property passed to it. This type of data set can be a list of items with a parent-child relationship where they need to refine the child results based on parent id in it.

In Angular applications, we can do so by using Filter Pipes which can be easily used on a data object with custom login.

The Pipe Filter we are going to discuss will take a custom [key] name on which we want to filter child values. For example, there are following two data sets:

  recipes = [
    {
       "id":1,
       "name":"Burger"
    },
    {
       "id":2,
       "name":"French Fries"
    },
    {
       "id":3,
       "name":"Chowmein"
    }
   ]
  
  
  ingredients = [
    {
       "id":1,
       "parentId":1,
       "name":"Potatoes"
    },
    {
       "id":2,
       "parentId":1,
       "name":"Beans"
    },
    {
       "id":3,
       "parentId":1,
       "name":"Buns"
    },
    {
       "id":4,
       "parentId":1,
       "name":"Carrots"
    },
    {
       "id":5,
       "parentId":2,
       "name":"Cooking Oil"
    },
    {
       "id":6,
       "parentId":2,
       "name":"Potatoes"
    },
    {
       "id":7,
       "parentId":2,
       "name":"Pepper"
    },
    {
       "id":8,
       "parentId":2,
       "name":"Salt"
    },
    {
       "id":9,
       "parentId":3,
       "name":"Hakka Noodles"
    },
    {
       "id":10,
       "parentId":3,
       "name":"Green Vegies"
    },
    {
       "id":11,
       "parentId":3,
       "name":"Tomato Sauce"
    },
    {
       "id":12,
       "parentId":3,
       "name":"Soya Souce"
    }
   ]</pre>
If we look at the objects above, in recipes there are two properties id and name. In the ingredients object, there is a parentId property that reflects the id of recipe.

To show ingredients of a particular recipe selected, we will create a generic Angular filter pipe, where we will pass the property name on which we want to filter out ingredients which is the <code>parentId here.

Create a Filter Pipe

Using NG CLI tool, we can create a new Filter pipe using the generate command s shown below:
$ ng generate pipe pipes/filterParent</pre>
Above command will create a new pipe file <strong>pipes/filter-parent.pipe.ts</strong> with the following code in it:
<pre class="wp-block-prismatic-blocks"><code class="language-javascript">import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'filterParent'
})
export class FilterParentPipe implements PipeTransform {

  transform(value: any, ...args: any[]): any {
    return null;
  }

}
</pre>
<div>
<div> For using a pipe in application components, we need to add it to its module's <code>declarations array.
As we have created it using NG CLI's generate command, so it will do it automatically:
// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { FilterParentComponentComponent } from './components/filter-parent-component/filter-parent-component.component';
import { FilterParentPipe } from './pipes/filter-parent.pipe';

@NgModule({
  declarations: [
    AppComponent,
    FilterParentComponentComponent,
    FilterParentPipe
  ],
  imports: [
    FormsModule, // <-- required to use [(ngModule)] in HTML component
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

What is an Angular Pipe?

An Angular pipe is a class with @Pipe decorator which implements the PipeTransform interface. The pipe is used to format or modify the output in some required way.

The PipeTransform interface provides the transform method which can take any number of required arguments with the first one required returns the object on which we apply the filter.

Properties of @Pipe Decorator

Pipe decorator takes two properties name(required) and pure(optional).
The name property is the string which we will use on an object like here we have 'filterParent'.

The pure property takes a boolean which is false by default. This property is used to enable force checking of object changes on every watch event on the component which can really adversely affect the application performance so this must be set to true only if required.

Let' move back to our filterParent pipe.

FilterParent pipe Upgrade

In our pipe, we want to filter out the object we get in value by the id of the recipe which we are getting in the parentId as a transform argument.

The keyName is the property name of the object on which we will do filtration:

// filter-parent.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import * as _ from 'lodash';

@Pipe({
  name: 'filterParent'
})
export class FilterParentPipe implements PipeTransform {

    transform(value: string, keyName: string, parentId: any, ): string {
        return _.filter(value, function (o) {
            return o[keyName] === +parentId;
        });
    }

}

Here we are using the lodash to use its filter method.

In the above code, we are using + in front of parentId to convert it into an int to match with o[keyName] using strict comparison (===).

Usage of Filter in Template

Usage of this pipe is very simple, just add it using a pipe operator as shown below with a property name and second argument as the id of recipe selected in the select box:

<h5>Select Recipe</h5>
<select name="recipes" [(ngModel)]="recipeModel">
    <option [value]="r.id" *ngFor="let r of recipes">{{r.name}}</option>
</select>

<h5>Ingredients</h5>
<ul>
    <li *ngFor="let ing of ingredients | filterParent:'parentId':recipeModel">
        {{ing.name}}
     </li>
</ul>

In the above code, we have used pipe on ingredients object.

That's it so here we got to know how to create a filter pipe in Angular to filter out child objects using a parent id or by any property passed to filter.

 

 

 

 

 

 

Leave a Comment

Your email address will not be published. Required fields are marked *