【问题标题】:Angular(5) - Use same pipe for two-level array dataAngular(5) - 对两级数组数据使用相同的管道
【发布时间】:2018-08-07 00:23:39
【问题描述】:

我正在尝试为两级 json 数据实现相同的管道,我在 html 中解析两个嵌套的 ngFor 循环。

home.component.html:

<div class="drop-type">
<div class="label">Multi-select two levels</div>

<div class="search-input-box">
  <input [(ngModel)]="searchValue" class="search-input" placeholder="Search...">

  <div *ngIf="searchValue && searchValue.length > 1" class="ac-list">
    <ul>
      <ng-container *ngFor="let value of values | value: searchValue">
        <li class="drop-item" (click)="selectMSTLItem(value)">
          <div class="check" [ngClass]="{'selected': value.selected}"></div>
          <div class="name">{{value.name}}</div>
        </li>
        <ng-container *ngFor="let subvalue of value.subitems | value: searchValue">
          <li class="drop-item sub-item" (click)="selectMSTLItem(subvalue)">
            <div class="check" [ngClass]="{'selected': subvalue.selected}"></div>
            <div class="name">{{subvalue.name}}</div>
          </li>
        </ng-container>
      </ng-container>
    </ul>
  </div>
</div>

<ng-container *ngFor="let selectedItem of values">
  <div class="selected-drop-item">
    <div *ngIf="selectedItem.selected" (click)="deselectMSTLItem(selectedItem)">{{selectedItem.name}}</div>
  </div>
  <ng-container *ngFor="let selectedSubItem of selectedItem.subitems">
    <div class="selected-drop-item">
      <div *ngIf="selectedSubItem.selected" (click)="deselectMSTLItem(selectedSubItem)">{{selectedSubItem.name}}</div>
    </div>
  </ng-container>
</ng-container></div>

home.component.ts:

import { Component, OnInit } from '@angular/core';
import {ValuesService} from './values.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.less']
})
export class HomeComponent implements OnInit {
  values: any[] = [];
  searchValue: string;

  constructor(private valuesService: ValuesService) {
  }

  ngOnInit() {
    this.valuesService.getValues()
      .subscribe(
        (response) => {
          this.values = response.results;
        },
        (error) => {
          console.log(error);
        }
      );
  }

  selectMSTLItem(selectedItem) {
    selectedItem.selected = !selectedItem.selected;
  }

  deselectMSTLItem(selectedItem) {
    selectedItem.selected = false;
  }
}

search.pipe.ts:

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

@Pipe({name: 'value'})
export class SearchPipe implements PipeTransform {
  transform(values: any, searchValue: any): any {
    if (searchValue == null) { return values; }

    return values.filter(function(value){
      return value.name.toLowerCase().indexOf(searchValue.toLowerCase()) > -1
        || value.subitems.name.toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
    });
  }
}

values.service.ts:

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class ValuesService {
  private _url = '../assets/values.json';

  constructor(private _http: Http) {}

  getValues () {
    return this._http.get(this._url)
      .map((response: Response) => response.json());
  }
}

values.json:

    {
  "results": [
    {
      "name": "Value 1.0",
      "selected": false,
      "subitems": [
        {
          "name": "Value 1.1",
          "selected": false
        },
        {
          "name": "Value 1.2",
          "selected": false
        },
        {
          "name": "Value 1.3",
          "selected": false
        }
      ]
    },
    {
      "name": "Value 2.0",
      "subitems": [
        {
          "name": "Value 2.1",
          "selected": false
        },
        {
          "name": "Value 2.2",
          "selected": false
        },
        {
          "name": "Value 2.3",
          "selected": false
        }
      ]
    },
    {
      "name": "Value 3.0",
      "subitems": [
        {
          "name": "Value 3.1",
          "selected": false
        },
        {
          "name": "Value 3.2",
          "selected": false
        },
        {
          "name": "Value 3.3",
          "selected": false
        }
      ]
    }
  ]
}

我想要完成的是,例如,当用户输入字符串“Va”时,它会列出所有包含字符串“va”的级别 1 和级别 2 名称值,现在它会这样做。但是,当用户想要搜索级别 2 元素并输入字符串“Value 1”时。 (搜索 Value 1.1 或 Value 1.2 等)我收到一个错误

TypeError:无法读取未定义的属性“toLowerCase”

管道中的第二个返回值 (value.subitems.name.toLowerCase().indexOf(searchValue.toLowerCase()) > -1)

我的猜测是,我需要以某种方式在管道中循环遍历所有 2 级元素,并过滤掉那些包含搜索值的元素,然后当然返回这些以及所有 1 级元素。有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: angular typescript pipe


    【解决方案1】:

    value.subitems 是您无法访问的数组value.subitems.name 试试这个:

    import {Pipe, PipeTransform} from '@angular/core';
    
    @Pipe({name: 'value'})
    export class SearchPipe implements PipeTransform {
      transform(values: any[], searchValue: any): any {
        if (searchValue == null) { return values; }
    
        return values.filter(v => this.filterFn(v, searchValue));
      }
    
      filterFn(value: any, searchValue) {
        let flag = this.testSearchCondition(value.name, searchValue);
        if (!flag && value.subitems) {
          flag = value.subitems.filter(v => this.testSearchCondition(v.name, searchValue)).length > 0;
        }
        return flag;
      }
      testSearchCondition(name: string, searchValue: string): boolean {
        return name.toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
      }
    }
    

    【讨论】:

    • 试过你的答案,但这是我得到的,查看图片:当我尝试搜索时:imgur.com/a/tvy8m,错误在哪里:imgur.com/a/DwnCB,错误是:imgur.com/a/BDdvp .
    • 对不起,我的错误`flag = value.subitems.filter(v => this.testSearchCondition(v.name, searchValue)).length > 0;` 而不是 `flag = value.subitems.filter (v => this.testSearchCondition(v, searchValue)).length > 0;` 现在可以了
    【解决方案2】:

    嵌套数组搜索使用下面的代码 这里 data.sub_categories 是嵌套数组

    import { Pipe, PipeTransform } from '@angular/core';
    
    @Pipe({
        name: 'category'
    })
    export class CategoryPipe implements PipeTransform {
    
        transform(value: any, args?: any): any {
            if (args === undefined || args === '') { return value; }
            return value.filter(data => { 
              return  data.category_name.toLowerCase().includes(args.toLowerCase())  || data.sub_categories.find(item => item.category_name.toLowerCase().includes(args.toLowerCase()));
    
            });
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-28
      • 2018-05-11
      • 2018-11-24
      • 1970-01-01
      • 2018-09-21
      相关资源
      最近更新 更多