Làm cách nào để áp dụng bộ lọc cho * ngFor?


278

Rõ ràng, Angular 2 sẽ sử dụng các đường ống thay vì các bộ lọc như trong Angular1 kết hợp với ng-for để lọc kết quả, mặc dù việc triển khai dường như vẫn còn mơ hồ, không có tài liệu rõ ràng.

Cụ thể là những gì tôi đang cố gắng đạt được có thể được xem từ góc độ sau đây

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

Làm thế nào để thực hiện như vậy bằng cách sử dụng đường ống?


8
Lưu ý rằng một thay đổi đột phá được giới thiệu trong phiên bản beta 17 cho ngFor liên quan đến biểu tượng băm. Cách chính xác là:<div *ngFor="let item of itemsList" *ngIf="conditon(item)" ...
Memet Olsen


11
@MemetOlsen nhận xét từ Gunter bên dưới: " *ngFor*ngIftrên cùng một yếu tố không được hỗ trợ. Bạn cần thay đổi thành hình thức rõ ràng cho một trong số họ"
The Red Pea

1
Ngay cả những gì OP yêu cầu, nó vẫn được khuyến nghị KHÔNG SỬ DỤNG PIPE để lọc hoặc đặt hàng trong Angular2 +. Thích có một thuộc tính lớp với các giá trị được lọc: angular.io/guide/pipes#appcill-no-filterpipe-or-orderbypipe
ylerjen 21/12/18

Câu trả lời:


395

Về cơ bản, bạn viết một đường ống mà sau đó bạn có thể sử dụng trong *ngForchỉ thị.

Trong thành phần của bạn:

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

Trong mẫu của bạn, bạn có thể truyền chuỗi, số hoặc đối tượng cho đường ống của mình để sử dụng để lọc trên:

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

Trong đường ống của bạn:

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

Hãy nhớ đăng ký đường ống của bạn trong app.module.ts; bạn không còn cần phải đăng ký các đường ống trong@Component

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

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

Đây là một Plunker giúp trình diễn việc sử dụng ống lọc tùy chỉnh và ống lát cắt tích hợp để hạn chế kết quả.

Xin lưu ý (như một số nhà bình luận đã chỉ ra) rằng có một lý do tại sao không có ống lọc tích hợp trong Angular.


6
Thanx, điều này hoạt động như dự định, nhưng đôi khi tốt hơn là kiểm tra xem mảng vật phẩm có được xác định và không null hay không, vì Ng2 có thể thử áp dụng bộ lọc trong khi "vật phẩm" vẫn chưa được xác định.
timmz 17/03/2016

1
Ngoài ra, tôi cần thêm lớp bộ lọc vào khai báo @Component. Giống như vậy: @Component ({... pipe: [MyFilterPipe]
Stephen

1
Tôi nghĩ rằng nó cũng cần dòng này ìf (! Item) trả về các mục; `trong trường hợp mảng trống.
Boštjan Pišler

2
Angular nói rằng việc sử dụng một ống có vấn đề thực hiện, vì vậy nên thực hiện lọc trên thành phần
Sebastián Rojas

3
Tôi muốn đề xuất bọc *ngForcác tham số trong ngoặc đơn, để tránh mọi nhầm lẫn và làm cho nó "chống thay đổi":<li *ngFor="let item of (items | myfilter:filterargs)">
Tomas

104

Rất nhiều bạn có cách tiếp cận tuyệt vời, nhưng mục tiêu ở đây là chung chung và xác định một đường ống mảng cực kỳ có thể tái sử dụng trong tất cả các trường hợp liên quan đến * ngFor.

callback.pipe.ts (đừng quên thêm phần này vào mảng khai báo của mô-đun của bạn)

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

Sau đó, trong thành phần của bạn, bạn cần thực hiện một phương thức với ký hiệu sau (mục: any) => boolean , ví dụ trong trường hợp của tôi, tôi gọi nó là bộ lọcUser, bộ lọc tuổi của người dùng lớn hơn 18 năm.

Thành phần của bạn

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

Và cuối cùng nhưng không kém phần quan trọng, mã html của bạn sẽ như thế này:

HTML của bạn

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

Như bạn có thể thấy, ống này khá chung chung trên tất cả các mảng như các mục cần được lọc thông qua một cuộc gọi lại. Trong mycase, tôi thấy nó rất hữu ích cho các kịch bản * ngFor like.

Hi vọng điêu nay co ich!!!

codematrix


4
Tôi nhận thấy rằng trong bộ lọc chức năngUser () - hoặc chức năng tương đương của tôi với điều đó - bạn không thể sử dụng "this" để truy cập vào thể hiện thành phần hiện tại như bạn có thể với tất cả các chức năng khác trong lớp thành phần. Tôi cần truy cập vào đối tượng thành phần để kiểm tra mục được lọc trong bộ sưu tập.
Paul

1
@Paul, hmm ... điều đó là không thể. Là phương pháp của bạn riêng tư? Không có vấn đề gì vì tư nhân chỉ là các cấu trúc biên dịch và không được thi hành trong thời gian chạy. Trong ví dụ của tôi, tôi đã sử dụng IUser. Điều này giả định rằng các mục trong bộ sưu tập được lặp lại bản đồ với nó. Bạn có thể thử bất kỳ để xem nếu nó hoạt động. Ngoài ra, hãy chắc chắn rằng tên được gõ đúng, trường hợp và tất cả.
mã5

1
Tôi không thể truy cập biến thành phần bằng phương pháp này
suulisin

10
Để tránh vấn đề thiskhông được xác định, bạn có thể viết phương thức của bạn trên thành phần của bạn filterUser = (user: IUser) =>chứ không phảifilteruser(user: IUser)
Tom

2
@Paul Tôi biết điều này là quá muộn để giúp bạn, nhưng nó có thể giúp những người khác. Lý do bạn thua thistrên phương thức thành phần của mình là vì phương thức này đã được sử dụng làm cuộc gọi lại và thisbối cảnh mới được áp dụng. Bạn gặp phải một vấn đề phổ biến trong javascript hướng đối tượng, nhưng có một giải pháp cũ và dễ dàng: bạn liên kết các phương thức được sử dụng làm cuộc gọi lại với lớp gốc. Trong hàm tạo của bạn, thêm mã sau đây: this.myCallbackFunc = this.myCallbackFunc.bind(this); Đó là nó. Bạn sẽ không bao giờ thua thislần nữa.
Randolpho

36

Cách đơn giản hóa (Chỉ được sử dụng trên các mảng nhỏ do vấn đề về hiệu suất. Trong các mảng lớn, bạn phải tạo bộ lọc theo cách thủ công thông qua mã):

Xem: https://angular.io/guide/pipes#appcill-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);
    }
}

Sử dụng:

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

Nếu bạn sử dụng một biến làm đối số thứ hai, đừng sử dụng dấu ngoặc kép.


3
Có thể thêm vào sau để hiển thị cách kết hợp nó với ReqExp: return items.filter (item => {return new RegExp (value, "i"). Test (item [field])});
Johannes

8
Theo nhóm Angular, đây được coi là thực hành xấu.

@torazaburo bạn có thể tham khảo ý kiến ​​của họ hoặc giải thích tại sao? Cảm ơn
Zymotik


2
Theo nhóm Angular, đây là mã kém vì nó chậm và không được khai thác tốt. Nhóm không muốn xem các trang web chậm do mã của họ nên lần này họ không xây dựng nó thành Angular. angular.io/docs/ts/latest/guide/ từ
Zymotik

29

Đây là những gì tôi thực hiện mà không cần sử dụng đường ống.

thành phần.html

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

thành phần

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

16
Tôi nghĩ rằng điều này sẽ được tính toán chuyên sâu vì Angular sẽ thực thi bộ lọc mỗi khi nó chạy phát hiện thay đổi. Nó sẽ không mở rộng tốt cho các mảng lớn. Một trình dọn dẹp, mặc dù mã phức tạp hơn, nhưng giải pháp sẽ là tạo itemListmột Observable và sử dụng bộ lọc async : let item of itemsList | async. Khi một sự thay đổi xảy ra, làm cho quan sát phát ra danh sách mới. Bằng cách này, mã lọc chỉ được chạy khi cần thiết.
BeetleJuice

1
Câu trả lời này nên có điểm tiêu cực. Thật tệ, sử dụng một đường ống.
Cétia

19

Tôi không chắc chắn khi nó đến nhưng họ đã tạo ra một lát cắt sẽ làm điều đó. Nó cũng được ghi chép lại.

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>

4
Nếu bạn sử dụng Giao diện trackBy , đường ống lát phải được áp dụng trước ;. ví dụ:*ngFor="let feature of content?.keyFeatures | slice:1:5; trackBy feature?.id"
Philip

11

Bạn cũng có thể sử dụng như sau:

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

Điều này sẽ chỉ hiển thị div nếu các mục của bạn phù hợp với điều kiện

Xem tài liệu góc để biết thêm thông tin Nếu bạn cũng cần chỉ mục, hãy sử dụng như sau:

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

1
Điều này sẽ không nhập mẫu cho mọi mục trong danh sách thay vì chỉ danh sách được lọc? Đó có thể là một hit hiệu suất.
Azeroth2b

8

ống trong Angular2 tương tự như ống trên dòng lệnh. Đầu ra của mỗi giá trị trước được đưa vào bộ lọc sau đường ống giúp dễ dàng xâu chuỗi các bộ lọc như thế này:

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

Xin lỗi nếu điều này là sai lệch, quan điểm của tôi ở đây là biến itemtừ *ng-for="#item of itemsList"nên được sử dụng để lọc kết quả như vậy *ng-if="conditon(item)". Điều này không hoạt động trong ví dụ này ..
Khaled

bạn có thể tạo điều kiện cho bộ lọc và thực hiện điều tương tự với {{item | condition}} điều kiện sẽ chỉ trả về itemnếu điều kiện được đáp ứng và không có giá trị nếu không.
Ben Glasser

@BenGlasser Tôi nghĩ đường ống được áp dụng từ phải sang trái. Vì vậy, điều này sẽ áp dụng bộ lọc2 trước, sau đó là bộ lọc1.
Evan Plaice

12
*ngFor*ngIftrên cùng một yếu tố không được hỗ trợ. Bạn cần thay đổi thành hình thức rõ ràng cho một trong số họ<template ngFor ...>
Günter Zöchbauer

1
@ GünterZöchbauer Phải mất một năm, nhưng tôi đã cập nhật cú pháp để phản ánh những thay đổi mà bạn đề xuất
Ben Glasser

5

Đối với yêu cầu này, tôi thực hiện và xuất bản một thành phần chung . Xem

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

Để sử dụng các thành phần này, trước đó, cài đặt gói này với npm:

npm install w-ng5 --save

Sau, nhập mô-đun trong app.module

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

Trong bước tiếp theo, thêm phần khai báo của app.module:

imports: [
  PipesModule,
  ...
]

Sử dụng mẫu

Lọc chuỗi đơn giản

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

Lọc chuỗi phức tạp - trường 'Giá trị' ở cấp 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>

Lọc chuỗi phức tạp - trường giữa - 'Giá trị' ở cấp 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>

Lọc mảng đơn giản phức tạp - trường 'Nome' cấp 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>

Lọc trong các trường cây - trường 'Valor' ở cấp 2 hoặc 'Valor' ở cấp 1 hoặc 'Nome' ở cấp 0

<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>

Lọc trường không tồn tại - 'Valor' ở mức 3 không tồn tại

<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>

Thành phần này hoạt động với cấp thuộc tính vô hạn ...


Xin chào, tôi ở đây và tôi đã làm theo tất cả các bước và trong trường hợp này tôi đang sử dụng cái này *ngFor="let inovice of invoices | filter:searchInvoice"và nó đang tìm kiếm trong danh sách của tôi, nhưng hiển thị một danh sách trống, bạn có biết tại sao không?
jecorrales

1
Xin chào, xin vui lòng cho tôi biết cấu trúc và loại đối tượng mà danh sách hóa đơn của bạn chứa. Cách bạn đang sử dụng chỉ nên được áp dụng nếu danh sách hóa đơn của bạn thuộc loại chuỗi. Nếu bạn muốn tìm kiếm theo số hóa đơn (bill.number), hãy sử dụng: * ngFor = "let inovice of Chemicals | filter: {field: number, value: searchInvoice}" . Nếu bạn muốn lọc theo hai cột, ví dụ: billing.customer.name , hãy sử dụng: * ngFor = "let inovice of Chemicals | filter: [field: number, value: searchInvoice}, {field: customer.name, value: searchInvoice}] .
Wedson Quintanilha da Silva

4

Một giải pháp đơn giản hoạt động với Angular 6 để lọc ngFor, đó là:

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

Khoảng cách là hữu ích vì vốn không đại diện cho bất cứ điều gì.


1
tốt hơn <span> là sử dụng <ng-container> vì nó sẽ không thêm bất kỳ đánh dấu không cần thiết nào ngoài tiếng ồn html có thể ảnh hưởng đến CSS của bạn.
Trevor de Koekkoek

4

Tôi biết đó là một câu hỏi cũ, tuy nhiên, tôi nghĩ rằng nó có thể hữu ích để cung cấp một giải pháp khác.

tương đương với AngularJS này

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

trong Angular 2+ bạn không thể sử dụng * ngFor và * ngNếu trên cùng một phần tử, vì vậy nó sẽ như sau:

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

và nếu bạn không thể sử dụng như bộ chứa nội bộ, hãy sử dụng ng-container thay thế. ng-container rất hữu ích khi bạn muốn nối một cách có điều kiện một nhóm các yếu tố (nghĩa là sử dụng * ng If = "foo") trong ứng dụng của bạn nhưng không muốn bọc chúng bằng một yếu tố khác.


4

Tôi đã tạo ra một plunker dựa trên các câu trả lời ở đây và các nơi khác.

Ngoài ra, tôi đã phải thêm một @Input, @ViewChildElementRefcủa <input>và tạo và subscribe()để có thể quan sát được nó.

Bộ lọc tìm kiếm Angular2: PLUNKR (CẬP NHẬT: plunker không còn hoạt động)


3

Ống sẽ là cách tiếp cận tốt nhất. nhưng dưới đây cũng sẽ làm việc.

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

Điều này có thể phá vỡ những điều nhất định. ví dụ bên trong một mat-form-field
pcnate

2

Đây là mã của tôi:

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

Mẫu vật:

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

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

1

Một cách tiếp cận khác mà tôi muốn sử dụng cho các bộ lọc dành riêng cho ứng dụng, là sử dụng thuộc tính chỉ đọc tùy chỉnh trên thành phần của bạn, cho phép bạn đóng gói logic lọc sạch hơn so với sử dụng ống tùy chỉnh (IMHO).

Ví dụ: nếu tôi muốn liên kết albumListvà lọc trên 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;
}

Để liên kết trong HTML, sau đó bạn có thể liên kết với thuộc tính chỉ đọc:

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

Tôi thấy đối với các bộ lọc chuyên biệt dành riêng cho ứng dụng, công cụ này hoạt động tốt hơn một đường ống vì nó giữ logic liên quan đến bộ lọc với thành phần.

Ống làm việc tốt hơn cho các bộ lọc tái sử dụng toàn cầu.


1
Phương pháp này có kích hoạt kiểm tra bẩn liên tục thay vì sử dụng phương pháp thay đổi giá trị không?
Léon Pelletier

1

Tôi đã tạo đường ống sau để lấy các mục mong muốn từ danh sách.

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

}

Chuyển đổi chữ thường chỉ để phù hợp trong trường hợp không nhạy cảm. Bạn có thể sử dụng nó trong quan điểm của bạn như thế này: -

<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>

1

Tốt nhất bạn nên tạo 2 ống angualr cho điều đó. Nhưng bạn có thể làm thủ thuật này.

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

1

Dựa trên giải pháp đường ống gọi lại rất thanh lịch được đề xuất ở trên, có thể khái quát hóa nó thêm một chút bằng cách cho phép các tham số bộ lọc bổ sung được truyền qua. Chúng tôi sau đó có:

gọi lại.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));
  }
}

thành phần

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>

0

Đây là một ví dụ mà tôi đã tạo ra một thời gian trước và viết blog về nó, bao gồm một plunk làm việc. Nó cung cấp một ống lọc có thể lọc bất kỳ danh sách các đối tượng. Về cơ bản, bạn chỉ cần chỉ định thuộc tính và giá trị {key: value} trong đặc tả ngFor của bạn.

Nó không khác nhiều so với phản hồi của @ NateMay, ngoại trừ việc tôi giải thích nó chi tiết tương đối dài dòng.

Trong trường hợp của tôi, tôi đã lọc một danh sách không có thứ tự trên một số văn bản (bộ lọc) mà người dùng đã nhập vào thuộc tính "nhãn" của các đối tượng trong mảng của tôi với loại đánh dấu này:

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

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


0

Bước đầu tiên bạn tạo Bộ lọc bằng cách sử dụng @Pipe tệp thành phần.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
    }
})

Và cấu trúc dữ liệu của đối tượng Person:

người

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

Theo quan điểm của bạn trong tệp 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>

0

Đây là mảng của bạn

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

        }
    ];

Đây là bộ lọc vòng lặp ngFor của bạn Bởi:

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

Có tôi đang sử dụng bộ lọc Sản phẩm ngay lập tức, vì tôi muốn lưu giữ dữ liệu gốc của mình. Ở đây model _filterText được sử dụng làm hộp đầu vào. Khi nào có bất kỳ chức năng setter thay đổi nào sẽ gọi. Trong setFilterText biểu diễn, sản phẩm được gọi, nó sẽ trả về kết quả chỉ những người phù hợp với đầu vào. Tôi đang sử dụng chữ thường cho trường hợp không nhạy cảm.

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

0

Sau vài lần googling, tôi đi qua ng2-search-filter. Trong sẽ lấy đối tượng của bạn và áp dụng thuật ngữ tìm kiếm đối với tất cả các thuộc tính đối tượng đang tìm kiếm sự trùng khớp.


0

Tôi đã tìm thấy đôi khi để tạo một bộ lọc đi qua một đối tượng, sau đó tôi có thể sử dụng nó như đa bộ lọc: Ví dụ đa bộ lọc

tôi đã làm Giải pháp làm đẹp này:

bộ lọc.pipe.ts

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

@Pipe({
  name: 'filterx',
  pure: false
})
export class FilterPipe implements PipeTransform {
 transform(items: any, filter: any, isAnd: boolean): any {
  let filterx=JSON.parse(JSON.stringify(filter));
  for (var prop in filterx) {
    if (Object.prototype.hasOwnProperty.call(filterx, prop)) {
       if(filterx[prop]=='')
       {
         delete filterx[prop];
       }
    }
 }
if (!items || !filterx) {
  return items;
}

return items.filter(function(obj) {
  return Object.keys(filterx).every(function(c) {
    return obj[c].toLowerCase().indexOf(filterx[c].toLowerCase()) !== -1
  });
  });
  }
}

thành phần

slotFilter:any={start:'',practitionerCodeDisplay:'',practitionerName:''};

Thành phần.html

             <tr>
                <th class="text-center">  <input type="text" [(ngModel)]="slotFilter.start"></th>
                <th class="text-center"><input type="text" [(ngModel)]="slotFilter.practitionerCodeDisplay"></th>
                <th class="text-left"><input type="text" [(ngModel)]="slotFilter.practitionerName"></th>
                <th></th>
              </tr>


 <tbody *ngFor="let item of practionerRoleList | filterx: slotFilter">...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.