我正在尝试为两级json数据实现相同的管道,我在两个嵌套的ngFor循环中用html解析。
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”时。 (搜索值1.1或值1.2等)我收到错误
TypeError:无法读取未定义的属性'toLowerCase'
在第二个返回值的管道中(value.subitems.name.toLowerCase()。indexOf(searchValue.toLowerCase())&gt; -1)
我的猜测是我需要以某种方式在管道中循环遍历所有2级元素,并过滤掉那些包含搜索值的元素,然后返回那些以及所有1级元素。有人可以帮我解决这个问题吗?
答案 0 :(得分: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;
}
}
答案 1 :(得分:1)
嵌套数组搜索使用以下代码 这里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()));
});
}
}