Как фильтровать массив с разными параметрами с помощью труб - PullRequest
1 голос
/ 16 октября 2019

Мой JSON файл с именем employee выглядит следующим образом:

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

У меня есть компонент с именем list, где я фильтрую это employees по их именам с помощью пользовательских каналов, например:

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);
    }
}

ТеперьЯ фильтрую, используя свойство name, но я хочу фильтровать, используя age, gender вместе с name. Используя то же поле ввода, я хочу фильтровать. Как мне этого добиться?

Ответы [ 4 ]

2 голосов
/ 16 октября 2019
 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
    })
}

Рабочая Stackblitz

2 голосов
/ 16 октября 2019

В этом случае вам нужно отфильтровать сотрудника в канале следующим образом:

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

И ваш код будет выглядеть примерно так:

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));
    }
}

Чтобы этот фильтр работалсмотрите это: массив фильтров javascript

2 голосов
/ 16 октября 2019

Просто используйте или оператор ||

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)
); 
0 голосов
/ 16 октября 2019

Создание канала для одного выхода не очень круто. Вы можете использовать его для компонента так:

get filteredEmployees() {

return employees.filter( anything you want )

}

В html просто вызовите команду {{ filteredEmployees }}.

Если такая фильтрация хотя бы немного сложна и распространена для нескольких компонентов, создайтесервис для хранения таких функций и вызова его в получателе выше

...