Angular 2如何通过管道与过滤展示多层级JSON实体
实现Angular中多层级实体的管道过滤展示
我来一步步帮你完成多层级数据的管道过滤和展示,结合你现有的类定义和数据服务,咱们从完善结构到落地实现:
1. 完善TypeScript类的类型匹配
首先咱们把类的结构和返回的JSON数据对齐,保证类型安全,同时保留你定义的核心属性:
Team.ts
import { Franchise } from './franchise'; export class Team { player_name: string; player_role: string; // 补充JSON里的其他可选属性,以及嵌套的球队实体 player_id?: number; player_type?: string; player_price?: number; player_points?: number | null; franchise: Franchise; constructor(data: Partial<Team>) { Object.assign(this, data); } }
Franchise.ts
export class Franchise { franchise_name: string; // 补充JSON里的其他可选属性 id?: number; franchise_id?: number; constructor(data: Partial<Franchise>) { Object.assign(this, data); } }
这样我们就能把服务返回的JSON数据无缝映射成Team类型的对象,避免类型报错。
2. 创建支持多层级过滤的自定义管道
接下来写一个自定义管道,既能过滤球员本身的属性(比如名字、角色),也能过滤嵌套的球队名称:
import { Pipe, PipeTransform } from '@angular/core'; import { Team } from './team'; @Pipe({ name: 'multiLevelFilter' }) export class MultiLevelFilterPipe implements PipeTransform { transform(teams: Team[], filterKeyword: string): Team[] { // 处理空数据或空关键词的情况 if (!teams.length || !filterKeyword) { return teams; } const lowerKeyword = filterKeyword.toLowerCase(); return teams.filter(team => { // 匹配球员名字、角色 const playerMatch = team.player_name.toLowerCase().includes(lowerKeyword) || team.player_role.toLowerCase().includes(lowerKeyword); // 匹配嵌套的球队名称 const franchiseMatch = team.franchise.franchise_name.toLowerCase().includes(lowerKeyword); return playerMatch || franchiseMatch; }); } }
记得把这个管道添加到你的模块(比如AppModule)的declarations数组中,不然Angular识别不了它。
3. 组件中调用服务并处理数据
在你的展示组件里,调用服务获取数据,然后转成Team类型的数组:
import { Component, OnInit } from '@angular/core'; import { YourDataService } from './your-data.service'; // 替换成你的服务类名 import { Team } from './team'; @Component({ selector: 'app-player-display', templateUrl: './player-display.component.html', styleUrls: ['./player-display.component.css'] }) export class PlayerDisplayComponent implements OnInit { playerList: Team[] = []; filterText: string = ''; // 绑定输入框的过滤关键词 constructor(private dataService: YourDataService) { } ngOnInit(): void { this.dataService.getPeople().subscribe(rawData => { // 如果返回的是单个对象,转成数组;如果是数组直接映射 const dataArray = Array.isArray(rawData) ? rawData : [rawData]; this.playerList = dataArray.map(item => new Team(item)); }); } }
4. 模板中使用管道渲染并过滤数据
最后在组件的HTML模板里,添加过滤输入框,配合*ngFor和自定义管道展示数据:
<!-- 过滤输入框 --> <input type="text" [(ngModel)]="filterText" placeholder="输入球员名/角色/球队名过滤"> <!-- 球员卡片列表 --> <div *ngFor="let player of playerList | multiLevelFilter: filterText" class="player-card"> <h3>{{ player.player_name }}</h3> <p>角色: {{ player.player_role }}</p> <p>所属球队: {{ player.franchise.franchise_name }}</p> <p>身价: {{ player.player_price | number }}</p> <p>积分: {{ player.player_points || '暂无数据' }}</p> </div>
可选扩展
如果需要更灵活的过滤规则(比如指定只过滤球队名),可以修改管道,让它接受第二个参数来指定过滤字段,比如:
// 管道修改后的transform方法 transform(teams: Team[], filterKeyword: string, targetFields?: string[]): Team[] { // ... return teams.filter(team => { if (targetFields?.length) { return targetFields.some(field => { // 处理嵌套字段,比如'franchise.franchise_name' const value = field.split('.').reduce((obj, key) => obj[key], team); return value?.toLowerCase().includes(lowerKeyword); }); } // 默认逻辑 return playerMatch || franchiseMatch; }); }
模板里就可以这样用:playerList | multiLevelFilter: filterText: ['franchise.franchise_name']
内容的提问来源于stack exchange,提问作者parthpar
相关产品推荐
相关产品推荐

