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

Angular下拉框加载API数据时报错TypeError: Cannot read properties of undefined (reading 'Id')

问题:Angular下拉框加载API数据时出现TypeError错误

问题场景

尝试从API获取数据并在下拉框中展示,运行时报错TypeError: Cannot read properties of undefined (reading 'Id')

HTML代码

<th>
  <select class="form-control" id="deviceTypeFilter" ngIf="deviceType" ng-options="deviceType for deviceType in vm.deviceTypes" ng-model="vm.selectedDeviceType" ng-change="vm.loadWithFilters()">
    <option value=""></option>
  </select>
</th>

TypeScript代码

export class FirmwaresController {
  isLoading: boolean = false;
  selectedDeviceType: string = null;
  selectedTenant: Tenant;

  deviceTypes: Array<string>;
  firmwares: Array<any>;
  firmwaresCnt: number;

  private logger: ILogger;

  constructor(private $stateParams: any,
    logger: LoggerService,
    private firmwareService: FirmwareService,
    private applicationService: ApplicationService,
    private modalService: ModalService,
    private $window: any,
    $scope: IScope) {

    this.setFilterCollections();
    this.loadFirmwares();
    this.selectedDeviceType = $stateParams.deviceType;
    this.applicationService.getCurrentTenant()
      .then((tenant) => {
        this.selectedTenant = tenant;
        this.loadFirmwares();
      })
      .finally(() => this.isLoading = false);
    this.logger = logger.getLogger('firmwares');
  }

  setFilterCollections() {
    this.firmwareService.getDeviceTypes(this.selectedTenant.Id).then((response: any) => this.deviceTypes = response);
  }

  loadFirmwares() {
    if (this.selectedDeviceType === null) {
      return;
    }
    this.isLoading = true;
    this.firmwares = new Array<any>();
    this.firmwareService.getFirmwares(this.selectedTenant.Id, this.queryFilter)
      .then((firmwares: Array<any>) => {
        angular.forEach(firmwares, (firmwares: any) => {
          this.firmwares.push(firmwares);
        });
      })
      .finally(() => this.isLoading = false);
  }

  loadWithFilters() {
    if (this.selectedTenant !== null) {
      this.currentPage = 1; // resetting to page 1 to avoid RangeNotSatisfiable errors
      this.loadFirmwares();
    }
  }
}

报错信息

TypeError: Cannot read properties of undefined (reading 'Id')
    at FirmwaresController.setFilterCollections (

解决方案

问题根源

构造函数中同步调用了setFilterCollections(),但此时selectedTenant是未定义状态——applicationService.getCurrentTenant()是异步请求,需要等待返回结果才能给selectedTenant赋值,同步代码先执行就会导致访问selectedTenant.Id时抛出错误。

修复步骤

  1. 调整异步代码执行顺序:将setFilterCollections()移到getCurrentTenant()的then回调中,确保拿到租户信息后再加载设备类型:
constructor(...) {
  // 移除原有的this.setFilterCollections();
  this.loadFirmwares();
  this.selectedDeviceType = $stateParams.deviceType;
  this.applicationService.getCurrentTenant()
    .then((tenant) => {
      this.selectedTenant = tenant;
      this.setFilterCollections(); // 移到此处
      this.loadFirmwares();
    })
    .finally(() => this.isLoading = false);
  this.logger = logger.getLogger('firmwares');
}
  1. 增加空值判断:在loadFirmwares()中补充selectedTenant的检查,避免同样的错误:
loadFirmwares() {
  if (this.selectedDeviceType === null || !this.selectedTenant) { // 新增判断
    return;
  }
  this.isLoading = true;
  this.firmwares = new Array<any>();
  this.firmwareService.getFirmwares(this.selectedTenant.Id, this.queryFilter)
    .then((firmwares: Array<any>) => {
      angular.forEach(firmwares, (firmware: any) => { // 修正变量名重复问题
        this.firmwares.push(firmware);
      });
    })
    .finally(() => this.isLoading = false);
}
  1. 修正HTML渲染条件:将ngIf="deviceType"改为ngIf="vm.deviceTypes",确保设备类型数据加载完成后再渲染下拉框:
<th>
  <select class="form-control" id="deviceTypeFilter" ngIf="vm.deviceTypes" ng-options="deviceType for deviceType in vm.deviceTypes" ng-model="vm.selectedDeviceType" ng-change="vm.loadWithFilters()">
    <option value=""></option>
  </select>
</th>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:17:29