* 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>
@Pipe
component.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
'IT story' 카테고리의 다른 글
유효한 UUID / GUID를 테스트하는 방법? (0) | 2020.04.22 |
---|---|
실행중인 화면 세션에서 스크롤 백 버퍼를 늘리려면 어떻게합니까? (0) | 2020.04.22 |
두 날짜 시간의 시차를 구하십시오. (0) | 2020.04.22 |
바이트 배열을 문자열로 변환하거나 그 반대로 변환하는 방법은 무엇입니까? (0) | 2020.04.22 |
입력 파일을 열 수 없습니다 : 장인 (0) | 2020.04.22 |