import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
public filter: string;
public items: Array = [
{
"name": "India",
"children": [
{
"name": "Delhi",
"children": [
{
"name": "South Delhi"
},
{
"name": "North Delhi"
}
]
},
{
"name": "Tamil Nadu",
"children": [
{
"name": "Chennai"
},
{
"name": "Coimbatore"
}
]
}
]
},
{
"name": "America",
"chilren": [
{
"name": "California",
"children": [
{
"name": "Trinity"
},
{
"name": "Yolo"
}
]
},
{
"name": "Florida",
"children": [
{
"name": "Bradford"
},
{
"name": "Calhoun"
}
]
}
]
}
]
}
How to Recursively Search JSON/Object in Angular using Angular Pipe

There are times you need to search nested JSON / Object. You know how to search the flattened objects, but you stuck with the nested children objects search. In this angular pipe tutorial, I am going to teach you how to create a recursive angular pipe which searches nested objects / JSON dynamically.
A Sample Nested JSON
[
{
"name": "India",
"children": [
{
"name": "Delhi",
"children": [
{
"name": "South Delhi"
},
{
"name": "North Delhi"
}
]
},
{
"name": "Tamil Nadu",
"children": [
{
"name": "Chennai"
},
{
"name": "Coimbatore"
}
]
}
]
},
{
"name": "America",
"chilren": [
{
"name": "California",
"children": [
{
"name": "Trinity"
},
{
"name": "Yolo"
}
]
},
{
"name": "Florida",
"children": [
{
"name": "Bradford"
},
{
"name": "Calhoun"
}
]
}
]
}
]
This JSON has a nested array of objects. It’s very easy to search the topmost array of objects in a single for loop but in the case of a nested array of objects, we can’t write nested for loops because we don’t know how deeper the nested JSON is.
SOLUTION FOR SEARCHING NESTED OBJECTS / JSON:
We can solve this nested loop problem by creating a recursive function. If the term ‘recursive’ is new to you, read the below definition
Recursion is a process in which a function calls itself as a subroutine. This allows the function to be repeated several times, since it calls itself during its execution. Functions that incorporate recursion are called recursive functions.
CREATE A ANGULAR PIPE
Angular Pipes are used to transforming the data in a more effective way rather than writing loops by ourselves. The angular pipe algorithm is very effective and fast.
Use the following command in your angular app to generate a angular pipe called recursive (whatever name you prefer).
ng generate pipe recursive
Open the generated pipe in your editor
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'recursive'
})
export class RecursiveSearchPipe implements PipeTransform {
transform(value: any): any {
return value;
}
}
The above code is generated by Angular, it has a “transform” method which is invoked when we use this pipe to modify our data. This method will always return the modified data.
Recursive Logic to Transform our data using this angular pipe:
In the generated code, we are going to add our custom logic for recursive search.
We create four properties in this pipe
searchedItems
– It is an Array used to store the searched results.key
– It’s a string typed by the user for the search.prop
– It is a string used to filter the search based on a particular property name in the JSON. E.g “label” or “name”chilrenPropName
– It is a string used to find the children property name in the JSON. E.g “child” or “children” etc.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'recursive'
})
export class RecursiveSearchPipe implements PipeTransform {
private searchedItems: Array<any> = [];
private key: string;
private prop: string;
private childrenPropName: string;
transform(value: any, key?: any, prop?: any, childrenProp?: any): any {
if(key != undefined) {
this.searchedItems = [];
this.key = key.toLowerCase();
this.prop = prop;
this.childrenPropName = childrenProp;
let searchResult = this.searchRecursive(value);
return searchResult;
}
return value;
}
searchRecursive(value) {
for(var i = 0; i < value.length; i++) {
let lowerCaseName = value[i][this.prop].toLowerCase();
if(lowerCaseName.includes(this.key)) {
this.searchedItems.push(value[i]);
} else if(value[i][this.childrenPropName]) {
if(value[i][this.childrenPropName].length > 0) {
this.searchRecursive(value[i][this.childrenPropName]);
}
}
}
return this.searchedItems;
}
}
Inside the transform
function, we first check the condition of the key
property, If the user has not typed any search string then it will return the full data.
If there’s a key then we assign the parameters to the class properties and invoke the method searchRecursive(value)
with the value as a parameter.
Search Recursive Method:
“searchRecursive” method is where all the recursive logic goes. This function calls itself as long as there’s a children property.
- First, it checks whether the
prop
(property name) of the JSON contains a key string. It can be easily achieved by usingincludes()
method in Javascript. - If the condition is true then the Object is pushed to the
searchedItems
Array else there’s another condition to check there’s any children property in the current Object. If it has one, then thesearchRecursive
function calls itself again with the children object as it’s parameter value. - This process goes on as long as there’s a children property in the JSON. All the search results are pushed to the
searchedItems
Array. - At last, it returns the
searchedItems
array to thetransform
method. The transform method again returns the modified data to us (templates)
Use the generated recursive angular pipe in a component
The “ng generate pipe” command automatically declares the pipe in app.module.ts. If it’s not declared, you should manually declare it in declarations array of NgModule
// other imports...
import { RecursiveSearchPipe } './RecursiveSearchPipe.pipe.ts';
@NgModule({
//...
declarations: [RecursiveSearchPipe],
//....
})
Let’s use the recursive pipe to search a tree, We are going to use bn-ng-tree which is an angular tree component. It already had a built-in search option using the recursive pipe. For our learning purpose, we are going to use our recursive pipe in the tree.
FULL CODE EXAMPLE FOR RECURSIVE SEARCH PIPE
<input type="text" name="search" [(ngModel)]="filter">
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'recursive'
})
export class RecursiveSearchPipe implements PipeTransform {
private searchedItems: Array = [];
private key: string;
private prop: string;
private childrenPropName: string;
transform(value: any, key?: any, prop?: any, childrenProp?: any): any {
if(key != undefined) {
this.searchedItems = [];
this.key = key.toLowerCase();
this.prop = prop;
this.childrenPropName = childrenProp;
let searchResult = this.searchRecursive(value);
return searchResult;
}
return value;
}
searchRecursive(value) {
for(var i = 0; i < value.length; i++) {
let lowerCaseName = value[i][this.prop].toLowerCase();
if(lowerCaseName.includes(this.key)) {
this.searchedItems.push(value[i]);
} else if(value[i][this.childrenPropName]) {
if(value[i][this.childrenPropName].length > 0) {
this.searchRecursive(value[i][this.childrenPropName]);
}
}
}
return this.searchedItems;
}
}
// other imports...
import { RecursiveSearchPipe } './RecursiveSearchPipe.pipe.ts';
@NgModule({
//...
declarations: [RecursiveSearchPipe],
//....
})
In our app.component.html, we are using our recursive pipe with ‘filter’ which is the ngModel of our search box, ‘name’ is the property name which we want to search, ‘children’ is the children property name inside our Object / JSON.
Whenever the user search using a country name in our JSON, our pipe will search deep down the tree to match any records. Our tree will get filtered based on the search.
I hope, You learned what is a recursive angular pipe and how to use it to search/filter JSON/Object. Remember, Pipes in angular are the most elegant way to modify data before visualizing it in templates