1

My JSON file called employee looks like this:

[
    {
        "id": "E01",
        "name": "neetha",
        "age": 20,
        "gender": "female",
    },
    {
        "id": "E02",
        "name": "Kiran",
        "age": 24,
        "gender": "male",
    },
   {
        "id": "E03",
        "name": "Jhon",
        "age": 28,
        "gender": "male",
    }   
]

I have an component called list where i am filtering this employees with their names using custom pipes like this:

list.component.html

<div>
    <mat-form-field>
        <input matInput [(ngModel)]="searchTerm"  placeholder="Search">
    </mat-form-field>
    <mat-selection-list class="list">
        <mat-list-option   *ngFor="let employee of employees | employeeFilter : searchTerm; let i=index">
            <a mat-list-item (click)="onSelect(employee,i)"><span>{{employee.name}}</span></a>
        </mat-list-option>
    </mat-selection-list>
</div>

employee-filter.pipe.ts

import { PipeTransform, Pipe } from '@angular/core';
import { Employee } from '../models/employee.model';

@Pipe({
    name: 'employeeFilter'
})
export class EmployeeFilterPipe implements PipeTransform {
    transform(employees: Employee[], searchTerm: string): Employee[] {
        if (!employees || !searchTerm) {
            return employees;
        }

        return employees.filter(employee =>
            employee.name.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1);
    }
}

Now the i am filtering using the name property, but i want to filter using age,gender along with name. Using the same input field i want to filter. How can i achieve this?

5
  • Just like you(?) did with the employee name Commented Oct 16, 2019 at 5:13
  • Pass an object instead of searchTerm Commented Oct 16, 2019 at 5:13
  • How can i pass object using input field? Commented Oct 16, 2019 at 5:15
  • Or don't complicate the things. Gonna respond below Commented Oct 16, 2019 at 5:15
  • @cuddlemeister If he will pass an object pipe will no trigger when value changes. Commented Oct 16, 2019 at 5:16

4 Answers 4

2

Just use or operator ||

return employees.filter(employee =>
            employee.name.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1)
|| employee.age.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1)
|| employee.gender.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1)
); 
Sign up to request clarification or add additional context in comments.

3 Comments

age is and number, cant use toLowerCase() method.
you can change it to age.toString()
Sorry it didn't worked for me ,soon i will update the stackblitz link.
2

In this case, you need to filter the employee in the pipe as follows:

return employees.filter((employee) => Object.values(employee).includes(searchTerm));

And your code will look like something:

import { PipeTransform, Pipe } from '@angular/core';
import { Employee } from '../models/employee.model';

@Pipe({
    name: 'employeeFilter'
})
export class EmployeeFilterPipe implements PipeTransform {
    transform(employees: Employee[], searchTerm: string): Employee[] {
        if (!employees || !searchTerm) {
            return employees;
        }

   //Parse a string to integer for the age
    let searchValue;
   if (!Number.isNaN(Number(searchTerm))) {
      searchValue = parseInt(searchTerm);
    } else {
      searchValue = searchTerm;
    }

        return employees.filter((employee) => (Object as any).values(employee).includes(searchValue));
    }
}

To see this filter working see this: javascript filter array of objects

2 Comments

Can you edit in this link : stackblitz.com/edit/…
@Shankar, See the forked and updated link: stackblitz.com/edit/…
1
 transform(employees: any[], searchTerm: string): any[] {

    if (!employees || !searchTerm) {
        return employees;
    }

    // remove the "id"
    const { id, ...objWithoutID } = employee;
    let values = Object.keys(objWithoutID).map(key => employee[key]);          
    // If you want fast and have a very large array of words, call toLowerCase once-  
    return values.join('|').toLowerCase().split('|').toString().indexOf(searchTerm.toString())!==-1
    })
}

Working Stackblitz

2 Comments

Is this efficient than using ||?
Of course yes. Dealing with the object/array is huge advantage when we have more data set.
0

Creating a pipe for a single output is not really cool. You can use it like that on the component:

get filteredEmployees() {

return employees.filter( anything you want )

}

In html just call use {{ filteredEmployees }}.

If such filtering is at least a bit complex and common for multiple components, create a service for storing such functions and call it in the getter above

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.