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时抛出错误。
修复步骤
- 调整异步代码执行顺序:将
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'); }
- 增加空值判断:在
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); }
- 修正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
相关产品推荐
相关产品推荐

