You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 4/5:按设备类型筛选下拉选项问题求助

解决方案:按设备类型筛选下拉选项

首先看你的代码,主要有几个问题导致筛选不生效:

  1. 不必要的重复API调用和错误的筛选逻辑
  2. 模板里没有根据当前设备类型ID过滤设备选项
  3. 存在语法和引用错误(比如trackStatusById方法未定义)

下面是具体的修复步骤:

1. 重构Component.ts的数据获取逻辑

你现在在循环里调用equipmentService.find完全多余——因为已经通过equipmentService.query()拿到了所有设备数据。而且嵌套订阅会让代码难以维护,建议用RxJS的forkJoin并行获取两类数据,同时可以提前把设备按equipmentTypeId分组,方便后续模板高效使用:

import { forkJoin } from 'rxjs';
// ... 其他必要导入

export class YourComponent {
  equipment: Equipment[];
  equipmentType: EquipmentType[];
  // 新增:按设备类型ID分组的设备映射
  equipmentByTypeId: { [key: number]: Equipment[] } = {};
  // 存储每个类型对应的选中设备ID
  selectedEquipmentIds: { [key: number]: number | null } = {};

  constructor(
    private equipmentService: EquipmentService,
    private equipmentTypeService: EquipmentTypeService
  ) {}

  ngOnInit() {
    // 并行获取设备类型和设备数据
    forkJoin([
      this.equipmentTypeService.query(),
      this.equipmentService.query()
    ]).subscribe(
      ([typeRes, equipRes]: [ResponseWrapper, ResponseWrapper]) => {
        this.equipmentType = typeRes.json;
        this.equipment = equipRes.json;
        
        // 按equipmentTypeId分组设备
        this.equipmentByTypeId = this.equipment.reduce((acc, equip) => {
          const typeId = equip.equipmentTypeId;
          if (!acc[typeId]) {
            acc[typeId] = [];
          }
          acc[typeId].push(equip);
          return acc;
        }, {} as { [key: number]: Equipment[] });
      },
      (res: ResponseWrapper) => this.onError(res.json)
    );
  }

  trackEquipmentById(index: number, item: Equipment) {
    return item.id;
  }

  trackEquipmentTypeById(index: number, item: EquipmentType) {
    return item.id;
  }

  // ... 你的onError错误处理方法
}

2. 修改Component.html实现筛选

现在可以用提前分组好的数据(性能更优),或者直接在模板内过滤,两种方式任选:

方式一:使用预分组数据(推荐,适合数据量较大的场景)

<div *ngFor="let equipmentOption of equipmentType; trackBy: trackEquipmentTypeById">
  <span>{{equipmentOption.description}}</span>
  <select 
    class="form-control" 
    id="field_issuedBy_{{equipmentOption.id}}" 
    name="issuedBy_{{equipmentOption.id}}" 
    [(ngModel)]="selectedEquipmentIds[equipmentOption.id]"
  >
    <option [ngValue]="null"></option>
    <option 
      [ngValue]="equipmentOpt.id" 
      *ngFor="let equipmentOpt of equipmentByTypeId[equipmentOption.id] || []; trackBy: trackEquipmentById"
    >
      {{equipmentOpt.description}}
    </option>
  </select>
</div>

注意:给每个select设置唯一的id和name,避免表单元素冲突;equipmentByTypeId[equipmentOption.id] || []是为了处理没有对应设备的类型,避免报错。

方式二:模板内直接过滤(简洁,适合小数据量场景)

如果不想提前分组,可以自定义一个过滤管道:

import { Pipe, PipeTransform } from '@angular/core';
import { Equipment } from './equipment.model';

@Pipe({ name: 'filterByEquipmentTypeId' })
export class FilterByEquipmentTypeIdPipe implements PipeTransform {
  transform(equipments: Equipment[], typeId: number): Equipment[] {
    if (!equipments || !typeId) return [];
    return equipments.filter(equip => equip.equipmentTypeId === typeId);
  }
}

别忘了在你的模块中声明这个管道。

然后修改模板:

<div *ngFor="let equipmentOption of equipmentType; trackBy: trackEquipmentTypeById">
  <span>{{equipmentOption.description}}</span>
  <select 
    class="form-control" 
    id="field_issuedBy_{{equipmentOption.id}}" 
    name="issuedBy_{{equipmentOption.id}}" 
    [(ngModel)]="selectedEquipmentIds[equipmentOption.id]"
  >
    <option [ngValue]="null"></option>
    <option 
      [ngValue]="equipmentOpt.id" 
      *ngFor="let equipmentOpt of equipment | filterByEquipmentTypeId: equipmentOption.id; trackBy: trackEquipmentById"
    >
      {{equipmentOpt.description}}
    </option>
  </select>
</div>

3. 修复原代码的其他小问题

  • 原模板中的trackStatusById改为trackEquipmentById,和component中定义的方法对应
  • 原component里的filterProtection筛选逻辑没有返回值,且条件错误(应该匹配equipmentTypeId而非设备ID)

这样修改后,每个设备类型对应的下拉框就只会显示属于该类型的设备选项了。

内容的提问来源于stack exchange,提问作者DESH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:23:39