为*ngFor的嵌套对象添加过滤功能
解决嵌套对象场景下管道过滤失效的问题
我之前也碰到过完全一样的情况!当把原本的字符串类型author改成嵌套对象后,原来的管道逻辑没适配这种变化,导致搜索功能直接罢工了。咱们一步步拆解问题,搞定它:
问题根源
原来的管道大概率是直接对比字符串值,比如像这样:
transform(items: any[], filterText: string): any[] { if (!items || !filterText) return items; return items.filter(item => item.author.toLowerCase().includes(filterText.toLowerCase()) ); }
现在item.author变成了对象({name: "...", age: ...}),直接拿它和输入的字符串比较的话,本质是把对象转成了[object Object]这个字符串去匹配,肯定找不到对应的结果,搜索自然就失效了。
解决方案
根据你的需求,有两种常见的处理方式:
1. 针对性修改管道(快速适配当前场景)
如果这个管道只用来处理书籍的作者搜索,直接把逻辑改成访问嵌套的name属性就行,记得加上可选链避免空值报错:
transform(items: any[], filterName: string): any[] { if (!items || !filterName) return items; const lowerFilter = filterName.toLowerCase(); return items.filter(item => // 用?.处理author可能为空的情况 item.author?.name.toLowerCase().includes(lowerFilter) ); }
模板里保持你的写法不变:
<input [(ngModel)]="filter.author.name" placeholder="搜索作者"> <div *ngFor="let book of books | yourPipeName: filter.author.name"> {{ book.title }} - {{ book.author.name }} </div>
2. 改成通用管道(支持任意嵌套属性)
如果以后还要处理其他嵌套字段的过滤,不如把管道改成支持属性路径的通用版本,比如:
transform(items: any[], filterValue: string, propertyPath: string): any[] { if (!items || !filterValue || !propertyPath) return items; const lowerFilter = filterValue.toLowerCase(); return items.filter(item => { // 解析属性路径,比如"author.name"拆成["author", "name"],逐层访问 const targetValue = propertyPath.split('.').reduce((currentObj, key) => { return currentObj?.[key]; }, item); return targetValue?.toString().toLowerCase().includes(lowerFilter); }); }
模板里使用的时候,要传入属性路径参数:
<input [(ngModel)]="filter.author.name" placeholder="搜索作者"> <div *ngFor="let book of books | yourPipeName: filter.author.name : 'author.name'"> {{ book.title }} - {{ book.author.name }} </div>
这样以后要搜索其他嵌套字段,比如book.publisher.address,只需要把属性路径改成'publisher.address'就行,复用性拉满。
额外提醒
一定要处理空值情况!比如有些书籍可能没有author字段,用?.可选链操作符可以避免出现Cannot read properties of undefined的报错,让你的代码更健壮。
内容的提问来源于stack exchange,提问作者Abdennacer Lachiheb
相关产品推荐
相关产品推荐

