IT story

* ngFor에 필터를 적용하는 방법?

hot-time 2020. 4. 22. 08:12
반응형

* ngFor에 필터를 적용하는 방법?


분명히 Angular 2는 Angular1에서와 같이 ng-for와 함께 필터 대신 파이프를 사용하여 결과를 필터링합니다. 구현이 여전히 모호한 것처럼 보이지만 명확한 문서는 없습니다.

즉, 내가 달성하려는 것은 다음 관점에서 볼 수 있습니다.

<div *ng-for="#item of itemsList" *ng-if="conditon(item)"></div>

파이프를 사용하여 구현하는 방법은 무엇입니까?


기본적으로 파이프를 작성하고 *ngFor지시문에 사용할 수 있습니다 .

컴포넌트에서 :

filterargs = {title: 'hello'};
items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];

템플릿에서 문자열, 숫자 또는 객체를 파이프에 전달하여 필터링 할 수 있습니다.

<li *ngFor="let item of items | myfilter:filterargs">

파이프에서 :

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'myfilter',
    pure: false
})
export class MyFilterPipe implements PipeTransform {
    transform(items: any[], filter: Object): any {
        if (!items || !filter) {
            return items;
        }
        // filter items array, items which match and return true will be
        // kept, false will be filtered out
        return items.filter(item => item.title.indexOf(filter.title) !== -1);
    }
}

파이프를 등록하십시오 app.module.ts; 더 이상 파이프를 등록 할 필요가 없습니다.@Component

import { MyFilterPipe } from './shared/pipes/my-filter.pipe';

@NgModule({
    imports: [
        ..
    ],
    declarations: [
        MyFilterPipe,
    ],
    providers: [
        ..
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

다음은 결과를 제한하기 위해 사용자 지정 필터 파이프와 내장 슬라이스 파이프의 사용을 시연 하는 Plunker 입니다.

제발 노트 (여러 주석이 지적한대로)하는 이유가 없음이 내장 된 이유 각도에서 필터 파이프.


많은 사람들이 훌륭한 접근 방식을 가지고 있지만 여기서 목표는 * ngFor와 관련하여 모든 경우에서 매우 재사용 가능한 배열 파이프를 일반화하고 정의하는 것입니다.

callback.pipe.ts (모듈의 선언 배열에 이것을 추가하는 것을 잊지 마십시오)

import { PipeTransform, Pipe } from '@angular/core';

@Pipe({
    name: 'callback',
    pure: false
})
export class CallbackPipe implements PipeTransform {
    transform(items: any[], callback: (item: any) => boolean): any {
        if (!items || !callback) {
            return items;
        }
        return items.filter(item => callback(item));
    }
}

그런 다음 구성 요소에서 다음과 같은 서명 (항목 : any) => boolean 을 사용하여 메소드를 구현해야합니다 . 예를 들어 필자는 필터 사용자라고 불렀으며 18 세 이상의 사용자 연령을 필터링했습니다.

구성 요소

@Component({
  ....
})
export class UsersComponent {
  filterUser(user: IUser) {
    return !user.age >= 18
  }
}

마지막으로 HTML 코드는 다음과 같습니다.

HTML

<li *ngFor="let user of users | callback: filterUser">{{user.name}}</li>

보시다시피이 파이프는 콜백을 통해 필터링해야하는 항목과 같은 모든 배열에서 상당히 일반적입니다. 제 경우에는 * ngFor like scenarios에 매우 유용하다는 것을 알았습니다.

도움이 되었기를 바랍니다!!!

코드 매트릭스


단순화 된 방법 (성능 문제로 인해 작은 배열에서만 사용됩니다. 큰 배열에서는 코드를 통해 수동으로 필터를 만들어야합니다) :

참조 : https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe

@Pipe({
    name: 'filter'
})
@Injectable()
export class FilterPipe implements PipeTransform {
    transform(items: any[], field : string, value : string): any[] {  
      if (!items) return [];
      if (!value || value.length == 0) return items;
      return items.filter(it => 
      it[field].toLowerCase().indexOf(value.toLowerCase()) !=-1);
    }
}

용법:

<li *ngFor="let it of its | filter : 'name' : 'value or variable'">{{it}}</li>

변수를 두 번째 인수로 사용하는 경우 따옴표를 사용하지 마십시오.


이것이 파이프를 사용하지 않고 구현 한 것입니다.

component.html

<div *ngFor="let item of filter(itemsList)">

component.ts

@Component({
....
})
export class YourComponent {
  filter(itemList: yourItemType[]): yourItemType[] {
    let result: yourItemType[] = [];
    //your filter logic here
    ...
    ...
    return result;
  }
}

언제 들어 왔는지 확실하지 않지만 이미 그렇게 할 수있는 슬라이스 파이프를 만들었습니다. 잘 문서화되어 있습니다.

https://angular.io/docs/ts/latest/api/common/index/SlicePipe-pipe.html

<p *ngFor="let feature of content?.keyFeatures | slice:1:5">
   {{ feature.description }}
</p>

다음을 사용할 수도 있습니다.

<template ngFor let-item [ngForOf]="itemsList">
    <div *ng-if="conditon(item)"></div>
</template>

아이템이 조건과 일치하는 경우에만 div가 표시됩니다

자세한 내용은 각도 설명서 를 참조하십시오. 인덱스가 필요한 경우 다음을 사용하십시오.

<template ngFor let-item [ngForOf]="itemsList" let-i="index">
    <div *ng-if="conditon(item, i)"></div>
</template>

Angular2의 파이프는 명령 행의 파이프와 유사합니다. 각 선행 값의 출력은 파이프 다음에 필터에 공급되어 다음과 같이 필터를 쉽게 연결할 수 있습니다.

<template *ngFor="#item of itemsList">
    <div *ngIf="conditon(item)">{item | filter1 | filter2}</div>
</template>

이 요구 사항에 대해서는 일반 구성 요소를 구현하고 게시합니다 . 보다

https://www.npmjs.com/package/w-ng5

이 구성 요소를 사용하려면 먼저 npm과 함께이 패키지를 설치하십시오.

npm install w-ng5 --save

그런 다음 app.module에서 모듈을 가져옵니다.

...
import { PipesModule } from 'w-ng5';

다음 단계에서 app.module의 선언 섹션에 추가하십시오.

imports: [
  PipesModule,
  ...
]

샘플 사용

간단한 문자열 필터링

<input type="text"  [(ngModel)]="filtroString">
<ul>
  <li *ngFor="let s of getStrings() | filter:filtroString">
    {{s}}
  </li>
</ul>

복잡한 문자열 필터링-레벨 2의 '값'필드

<input type="text"  [(ngModel)]="search">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.n2.valor2', value: search}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

복잡한 문자열 필터링-중간 필드-레벨 1의 '값'

<input type="text"  [(ngModel)]="search3">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.valor1', value: search3}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

복잡한 배열 단순 필터링-필드 'Nome'레벨 0

<input type="text"  [(ngModel)]="search2">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'nome', value: search2}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

트리 필드에서 필터링-레벨 2의 'Valor'필드 또는 레벨 1의 'Valor'또는 레벨 0의 'Nome'

<input type="text"  [(ngModel)]="search5">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.n2.valor2', value: search5}, {field:'n1.valor1', value: search5}, {field:'nome', value: search5}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

존재하지 않는 필드 필터링-존재하지 않는 레벨 3의 'Valor'

<input type="text"  [(ngModel)]="search4">
<ul>
  <li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.n2.n3.valor3', value: search4}]">
    {{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
  </li>
</ul>

이 구성 요소는 무한 속성 수준에서 작동합니다 ...


나는 여기와 다른 곳의 답변을 기반으로 플런저를 만들었습니다.

또한 나는 추가했다 @Input, @ViewChild하고 ElementRef의를 <input>작성하고 subscribe()그것의 관찰에.

Angular2 검색 필터 : PLUNKR (업데이트 : 플런 커가 더 이상 작동하지 않음)


파이프가 가장 좋습니다. 그러나 아래 하나도 효과가 있습니다.

<div *ng-for="#item of itemsList">
  <ng-container *ng-if="conditon(item)">
    // my code
  </ng-container>
</div>

응용 프로그램 별 필터에 사용하려는 또 다른 방법은 구성 요소에서 사용자 지정 읽기 전용 속성을 사용하여 사용자 지정 파이프 (IMHO)를 사용하는 것보다 필터링 논리를보다 깨끗하게 캡슐화하는 것입니다.

예를 들어 바인딩 albumList하고 필터링 하려는 경우 searchText:

searchText: "";
albumList: Album[] = [];

get filteredAlbumList() {
    if (this.config.searchText && this.config.searchText.length > 1) {
      var lsearchText = this.config.searchText.toLowerCase();
      return this.albumList.filter((a) =>
        a.Title.toLowerCase().includes(lsearchText) ||
        a.Artist.ArtistName.toLowerCase().includes(lsearchText)
      );
    }
    return this.albumList;
}

HTML에 바인딩하려면 읽기 전용 속성에 바인딩하면됩니다.

<a class="list-group-item"
       *ngFor="let album of filteredAlbumList">
</a>

응용 프로그램에 특화된 특수 필터의 경우 파이프와 비교하여 필터와 관련된 논리를 구성 요소와 함께 유지하므로 파이프보다 더 효과적입니다.

파이프는 전 세계적으로 재사용 가능한 필터에 더 적합합니다.


목록에서 원하는 항목을 가져 오기 위해 다음 파이프를 만들었습니다.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {

  transform(items: any[], filter: string): any {
    if(!items || !filter) {
      return items;
    }
    // To search values only of "name" variable of your object(item)
    //return items.filter(item => item.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1);

    // To search in values of every variable of your object(item)
    return items.filter(item => JSON.stringify(item).toLowerCase().indexOf(filter.toLowerCase()) !== -1);
  }

}

소문자 변환은 대소 문자를 구분하지 않는 방식으로 만 일치합니다. 다음과 같이 뷰에서 사용할 수 있습니다.

<div>
  <input type="text" placeholder="Search reward" [(ngModel)]="searchTerm">
</div>
<div>
  <ul>
    <li *ngFor="let reward of rewardList | filter:searchTerm">
      <div>
        <img [src]="reward.imageUrl"/>
        <p>{{reward.name}}</p>
      </div>
    </li>
  </ul>
</div>

이상적으로는 angualr 2 파이프를 만들어야합니다. 그러나이 트릭을 수행 할 수 있습니다.

<ng-container *ngFor="item in itemsList">
    <div*ngIf="conditon(item)">{{item}}</div>
</ng-container>

Angular 6과 함께 작동하여 ngFor를 필터링하는 간단한 솔루션은 다음과 같습니다.

<span *ngFor="item of itemsList"  >
  <div *ngIf="yourCondition(item)">
    
    your code
    
  </div>
</span

스팸은 본질적으로 어떤 것도 나타내지 않기 때문에 유용합니다.


나는 그 오래된 질문을 알고 있지만 다른 솔루션을 제공하는 것이 도움이 될 것이라고 생각했습니다.

이것의 AngularJS와 동등

<div *ng-for="#item of itemsList" *ng-if="conditon(item)"></div>

Angular 2 이상에서는 동일한 요소에서 * ngFor 및 * ngIf를 사용할 수 없으므로 다음과 같습니다.

<div *ngFor="let item of itemsList">
     <div *ngIf="conditon(item)">
     </div>
</div>

내부 컨테이너로 사용할 수 없으면 ng-container를 대신 사용하십시오. ng-container는 애플리케이션에 요소 그룹을 조건부로 추가 (예 : * ngIf = "foo"사용)하고 싶지만 다른 요소로 감싸고 싶지 않을 때 유용합니다.


이것은 내 코드입니다.

import {Pipe, PipeTransform, Injectable} from '@angular/core';

@Pipe({
    name: 'filter'
})
@Injectable()
export class FilterPipe implements PipeTransform {
    transform(items: any[], field : string, value): any[] {
      if (!items) return [];
      if (!value || value.length === 0) return items;
      return items.filter(it =>
      it[field] === value);
    }
}

견본:

LIST = [{id:1,name:'abc'},{id:2,name:'cba'}];
FilterValue = 1;

<span *ngFor="let listItem of LIST | filter : 'id' : FilterValue">
                              {{listItem .name}}
                          </span>

다음은 작동하는 플 런크를 포함하여 잠시 뒤로 만들고 블로그에 올린 예입니다. 모든 객체 목록을 필터링 할 수있는 필터 파이프를 제공합니다. 기본적으로 ngFor 사양 내에 속성과 값 {key : value}을 지정하면됩니다.

@NateMay의 응답과 크게 다르지 않습니다. 단지 비교적 자세하게 설명합니다.

필자의 경우 사용자가 입력 한 일부 텍스트 (filterText)의 정렬되지 않은 목록을 다음과 같은 마크 업을 사용하여 배열에있는 객체의 "label"속성에 대해 필터링했습니다.

<ul>
  <li *ngFor="let item of _items | filter:{label: filterText}">{{ item.label }}</li>
</ul>

https://long2know.com/2016/11/angular2-filter-pipes/


위에서 제안한 매우 우아한 콜백 파이프 솔루션을 기반으로 추가 필터 매개 변수를 전달하여 조금 더 일반화 할 수 있습니다. 우리는 다음을 가지고 있습니다.

callback.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'callback',
  pure: false
})
export class CallbackPipe implements PipeTransform {
  transform(items: any[], callback: (item: any, callbackArgs?: any[]) => boolean, callbackArgs?: any[]): any {
    if (!items || !callback) {
      return items;
    }
    return items.filter(item => callback(item, callbackArgs));
  }
}

구성 요소

filterSomething(something: Something, filterArgs: any[]) {
  const firstArg = filterArgs[0];
  const secondArg = filterArgs[1];
  ...
  return <some condition based on something, firstArg, secondArg, etc.>;
}

html

<li *ngFor="let s of somethings | callback : filterSomething : [<whatWillBecomeFirstArg>, <whatWillBecomeSecondArg>, ...]">
  {{s.aProperty}}
</li>

@Pipecomponent.ts 파일에서 필터를 사용하는 첫 번째 단계 :

your.component.ts

import { Component, Pipe, PipeTransform, Injectable } from '@angular/core';
import { Person} from "yourPath";

@Pipe({
  name: 'searchfilter'
})
@Injectable()
export class SearchFilterPipe implements PipeTransform {
  transform(items: Person[], value: string): any[] {
    if (!items || !value) {
      return items;
    }
    console.log("your search token = "+value);
    return items.filter(e => e.firstName.toLowerCase().includes(value.toLocaleLowerCase()));
  }
}
@Component({
  ....
    persons;

    ngOnInit() {
         //inicial persons arrays
    }
})

Person 객체의 데이터 구조 :

person.ts

export class Person{
    constructor(
        public firstName: string,
        public lastName: string
    ) { }
}

html 파일의보기에서 :

your.component.html

    <input class="form-control" placeholder="Search" id="search" type="text" [(ngModel)]="searchText"/>
    <table class="table table-striped table-hover">
      <colgroup>
        <col span="1" style="width: 50%;">
        <col span="1" style="width: 50%;">
      </colgroup>
      <thead>
        <tr>
          <th>First name</th>
          <th>Last name</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let person of persons | searchfilter:searchText">
          <td>{{person.firstName}}</td>
          <td>{{person.lastName}}</td>
        </tr>
      </tbody>
    </table>

이것은 당신의 배열입니다

products: any = [
        {
            "name": "John-Cena",
                    },
        {
            "name": "Brock-Lensar",

        }
    ];

이것은 ngFor 루프입니다.

<input type="text" [(ngModel)]='filterText' />
    <ul *ngFor='let product of filterProduct'>
      <li>{{product.name }}</li>
    </ul>

원래 데이터를 보존하고 싶기 때문에 filterProduct 제품 인스턴트를 사용하고 있습니다. 여기서 모델 _filterText는 입력 상자로 사용되며 변경 설정 기능이있을 때마다 호출됩니다. setFilterText에서 performProduct가 호출되면 입력과 일치하는 사람들 만 결과를 리턴합니다. 대소 문자를 구분하지 않기 위해 소문자를 사용하고 있습니다.

filterProduct = this.products;
_filterText : string;
    get filterText() : string {
        return this._filterText;
    }

    set filterText(value : string) {
        this._filterText = value;
        this.filterProduct = this._filterText ? this.performProduct(this._filterText) : this.products;

    } 

    performProduct(value : string ) : any {
            value = value.toLocaleLowerCase();
            return this.products.filter(( products : any ) => 
                products.name.toLocaleLowerCase().indexOf(value) !== -1);
        }

인터넷 검색 후, 나는 가로 질러왔다 ng2-search-filter. 에서 개체를 가져와 일치하는 모든 개체 속성에 대해 검색어를 적용합니다.

참고 URL : https://stackoverflow.com/questions/34164413/how-to-apply-filters-to-ngfor

반응형