Angular2过滤器/管道使用单选按钮进行过滤

时间:2017-07-03 04:05:08

标签: angular

我正在寻找一种过滤解决方案,它将过滤一组重复的元素。我在答案here中找到了一个基本的管道解决方案。

我发现<input [(ngModel)]='query'/>仅在同一组件内才有效。

但是 - 我需要让过滤器值来自另一个组件中预先填充的单选按钮。

到目前为止,这是我的代码。

filter.component

<div class="topic" *ngFor="let topic of topics">
  {{topic.term}}
  <input [(ngModel)]="query" type="radio" name="topicFilter" [value]="topic.term"/>
</div>

grid.component

<router-outlet></router-outlet> // this pulls in the filter.component

<input [(ngModel)]="query"> // this is a text input that works as wanted ( for showing what I'm wanting to achieve )

<grid-item *ngFor="let user of users | topicFilterPipe: 'topic':query">
  <a [routerLink]="['user-story', user.uid]">
    <h1>{{user.fname}}</h1>
  </a>
  {{user.topic}}
</grid-item>

filter.pipe

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

@Pipe({
  name: 'topicFilterPipe'
})
export class TopicFilterPipePipe implements PipeTransform {

  public transform(value: Array<any>, keys: string, term: string) {
    console.log('pipe has run');
    if (!term) return value;
    return (value || []).filter((item) => keys.split(',').some(key => item.hasOwnProperty(key) && new RegExp(term, 'gi').test(item[key])));

  }

}

基本上 - 尝试实现与文本输入相同的方法,但使用filter.component内选定的无线电。但是我正在努力将选定的值传递给管道和管道。然后使用ngModel过滤。谢谢!

注意:我对angular2 +非常新。过滤器组件必须保留在单独的组件中

2 个答案:

答案 0 :(得分:1)

您的问题是关于组件之间的通信。 FilterComponent需要通知GridComponent新查询已更新。

由于Service是Angular中的单例(例外存在但不相关)如果我们从一个组件设置服务中的数据,则其他组件可以访问数据。我们使用BehaviorSubject来存储信息,从而使用Observer模式。

QueryService:

此服务将包含查询数据。 getQuery将提供一个可由任何组件收听的可观察对象。

@Injectable()
export class QueryService{

    public query = new BehaviorSubject<string>('');

    public getQuery(){
        return query;
    }

    public setQuery(queryStr){
        this.query.next(queryStr);
    }
}

<强> FilterComponent

FilterComponent将调用服务并在值更改时更新。

HTML

<input 
    [ngModel]="query"
    (ngModelChange)="updateQuery($event)" 
    type="radio"
    name="topicFilter" [value]="topic.term"/>

TS

constructor(private queryService: QueryService){}
public updateQuery(query){
    queryService.setQuery(query);
}

<强> GridComponent

public query:string; 

constructor(private queryService: QueryService){}

ngOnInit(){
  // .... other code
  queryService.getQuery()
     .subscribe(queryVal => {
          this.query = queryVal;
     });

}

OR

您可以使用角度事件机制并触发事件,以便gridcomponent可以捕获事件并获取新查询。但服务方式做得更好。由于路由器内部有FilterComponent,因此其难以使用的事件机制。

在任何一种情况下,您都可以使用问题中提到的管道。

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

@Pipe({
  name: 'topicFilterPipe'
})
export class TopicFilterPipePipe implements PipeTransform {

  public transform(value: Array<any>, keys: string, term: string) {
    console.log('pipe has run');
    if (!term) return value;
    return (value || []).filter((item) => keys.split(',').some(key => item.hasOwnProperty(key) && new RegExp(term, 'gi').test(item[key])));

  }

}

您可以使用问题中提到的管道,也可以直接在组件中自行过滤列表。

如果您仍有问题,请创建一个plnkr,我可以使用此答案为您更新。

答案 1 :(得分:0)

您可以使用以下方法构建服务:

performFilter(filterBy: string): IProduct[] {
    filterBy = filterBy.toLocaleLowerCase();
    return this.products.filter((product: IProduct) =>
          product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
}

这是过滤产品列表...但您可以定制它以过滤您需要的任何内容。由于这需要在服务中以便可以共享,因此您很可能需要传入列表进行过滤。更像这样:

performFilter(products: IProduct[], filterBy: string): IProduct[] {
    filterBy = filterBy.toLocaleLowerCase();
    return products.filter((product: IProduct) =>
          product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
}