在角度中仅使用管道搜索一个场

时间:2017-11-15 12:50:06

标签: angular angular-services angular-forms angular-pipe

我有这个项目列表在我的JSON中,我只想搜索项目名称而忽略其他字段。我现在的问题是它还搜索其他字段。如何只在我的管道中使用项目名称进行搜索而不影响它的其他字段。这是我在下面所做的。

  

JSON

{
  "token": "ejsk0e",
  "projects": [
    {
      "id": 5,
      "name": "Store",
      "description": "Small",
      "organization_id": 1,
      "created_at": "2017-10-29 10:31:50",
      "updated_at": "2017-11-14 06:27:03",
      "material_projects": [
        {
          "id": 18,
          "material_id": 40,
          "project_id": 5,
          "quantity": 10,
          "unit": "pcs",
          "created_at": "2017-11-02 09:57:14",
          "updated_at": "2017-11-02 09:57:14",
          "material": {
            "id": 40,
            "sku": "ACWNAIL",
            "name": "Banana",
            "created_at": "2017-10-26 03:19:54",
            "updated_at": "2017-10-26 03:23:21"
          },
          "categories": [
            {
              "id": 8,
              "name": "Fruits",
              "created_at": "2017-10-26 07:36:48",
              "updated_at": "2017-11-10 02:06:07",
              "pivot": {
                "material_proj_id": 18,
                "category_id": 8
              }
            }
          ],
          "material_name": "Banana",
          "material_sku": "ACWNAIL",
          "category_name": "Fruits"
        }
  ]
}
  

TS

 getAllProjects() {
    this.subscription = this.projectsService.getAll()
      .subscribe(
        (data:any) => {
          this.projects = data.projects;
        },
        error => {
          console.log(error);
        });
  }
  

HTML

<div class="container-fluid">
  <input placeholder="Search..."" type="text" [(ngModel)]="searchProj">
  <div class="row" *ngFor="let project of projects | search : searchProj">
    <div class="card-block">
      <h2 class="proj-name">{{ project.name }}</h2>
    </div>
  </div>
</div>
  

PIPE.ts

export class SearchPipe implements PipeTransform {

      transform(items: any, term: any): any {
        if (term === undefined) return items;

        return items.filter(function(item) {
          for(let property in item){
            if (item[property] === null){
              continue;
            }
            if(item[property].toString().toLowerCase().includes(term.toLowerCase())){
              return true;
            }
          }
          return false;
        });
      }
    }

1 个答案:

答案 0 :(得分:0)

解决问题的方法是将属性作为变量提供给管道:

transform(items: any, term: any, prop: string): any {
    if (!term || !prop) return items;

    return items.filter((item) => 
        item[prop].toString().toLowerCase().includes(term.toLowerCase()));
  }


<div class="row" *ngFor="let project of projects | search : searchProj : 'name'">

...无论其

您永远不应该在管道转换中执行排序和过滤等操作。管道转换触发每个单独的更改检测周期,这是非常频繁的,这导致在每个更改检测周期重新应用排序和过滤,无论它们是否需要,这导致极差的应用程序性能。事实上,angularJS包括一个过滤管,但由于广泛滥用导致应用程序性能不佳而被删除。更好的方法是建立一个逻辑,当你需要自己触发排序或过滤而不是依靠变化检测来为你做。

使用反应式表单而不是ngModel会更容易,因此我的示例将使用它。

TS:

this.projects$ = this.projectsService.getAll();
this.searchProj = new FormControl('');
this.search$ = this.searchProj.valueChanges.startWith('').debounce(300).distinctUntilChanged();
this.filteredProjects$= Observable.combineLatest(this.projects$, this.search$)
                                  .map(([projects, searchTerm]) => (searchTerm) ? projects.filter(p => p.name.toString().toLowerCase().includes(searchTerm.toLowerCase()) : projects);

然后你的html:

<div class="container-fluid">
  <input placeholder="Search..."" type="text" [formControl]="searchProj">
  <div class="row" *ngFor="let project of filteredProjects$ | async">
    <div class="card-block">
      <h2 class="proj-name">{{ project.name }}</h2>
    </div>
  </div>
</div>

引导您完成此代码,首先存储用于在可观察项中检索项目的服务方法,然后为搜索项创建表单控件,然后将其值更改方法存储在observable中,首先告诉它从一个空值开始,然后去除它,只获取distnct值(这是一个小的优化,这样如果用户快速键入你实际上只搜索每两个字符,不研究他们是否快速输入和删除一个字符)。然后将这两个组合在一个新的observable中,并将它们一起映射到过滤器函数中,以便每次项目更改时都会过滤项目。

至于你原来的问题......现在这是一个非因素,因为你没有使用通用的东西作为管道,你可以只显式过滤name属性,或者你可以只采取上面的转换函数如果经常使用过滤逻辑,请在地图运算符中使用它。