Angular 11中ngOnInit()无法获取接口返回的Properties属性值问题
问题根因
HTTP请求属于异步操作,你在constructor中发起的接口请求不会阻塞后续代码执行,ngOnInit生命周期触发时,接口还没有返回数据,this.leave还未完成赋值,此时访问它的属性自然会抛出undefined错误。
解决步骤
1. 调整请求逻辑,数据返回后更新表单
将表单赋值操作放到接口请求的订阅回调中,确保拿到数据后再操作对应字段,参考修改后的组件代码:
import { HttpClient } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormControl, FormGroup} from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { AuthenticationService } from 'src/app/authentication.service'; import { Leave } from '../interfaces/leave'; import { LeaveService } from '../services/leave.service'; @Component({ selector: 'app-add-edit-leave', templateUrl: './add-edit-leave.component.html', styleUrls: ['./add-edit-leave.component.css'] }) export class AddEditLeaveComponent implements OnInit { form: FormGroup; currentDate = new Date(); minDate: Date; maxDate: Date; selectedFile: File = null; url : any; leave :Leave; constructor( private fb: FormBuilder, private http: HttpClient, private leaveService : LeaveService, private route : ActivatedRoute, private authenticationService: AuthenticationService ) { const currentYear = new Date().getFullYear(); this.minDate = new Date(currentYear - 20, 0, 1); this.maxDate = new Date(currentYear + 1, 11, 31); } ngOnInit() { // 先完成表单初始化 this.form = this.fb.group({ currentDate: new FormControl(this.currentDate.toISOString().split("T")[0]), joiningDate:[''], fromDate:[''], tillDate:[''], leaveType:[''], duration:[''], reason:[''], filePath:[''] }); // 发起接口请求,拿到数据后更新表单和leave实例 this.leaveService.applyLeaveGet(this.authenticationService.getUserId()) .subscribe(data => { this.leave = data; // 把接口返回的字段更新到响应式表单中 this.form.patchValue({ joiningDate: data.joiningDate // 其余需要回显的字段都可以在这里补充赋值 }) }); } onSelectFile(event: any) { this.selectedFile = <File>event.target.files[0]; if (event.target.files && event.target.files[0]) { var reader = new FileReader(); reader.onload = (event: any) => { this.url = event.target.result; } reader.readAsDataURL(event.target.files[0]); } else { this.url = ""; } } onSubmit(){ var userId = this.authenticationService.getUserId(); const formData = new FormData(); formData.append('userId', userId); // 注意此处原代码所有字段都取了this.form.value.fullName属于笔误,需要替换为对应表单字段取值 formData.append('currentDate', this.form.value.currentDate); formData.append('joiningDate', this.form.value.joiningDate); formData.append('fromDate', this.form.value.fromDate); formData.append('tillDate', this.form.value.tillDate); formData.append('leaveType', this.form.value.leaveType); formData.append('duration', this.form.value.duration); formData.append('reason', this.form.value.reason); formData.append('balanceAnnualLeave', this.leave.balanceAnnualLeave); formData.append('balanceSickLeave', this.leave.balanceSickLeave); formData.append('File', this.selectedFile); } }
2. 修复模板渲染报错
HTML模板中直接访问leave的属性会在数据返回前抛出错误,有两种修复方式:
- 方案一:使用可选链操作符
<li> annualLeaveBalacne: <span>{{leave?.balanceAnnualLeave}}</span> <br> </li> <li> sickLeaveBalance: <span>{{leave?.balanceSickLeave}}</span> </li>
- 方案二:增加ngIf判断,只有leave存在时才渲染对应模块
<div class="col-md-6" *ngIf="leave"> <mat-label>Leave Balacne</mat-label><br> <ul> <li> annualLeaveBalacne: <span>{{leave.balanceAnnualLeave}}</span> <br> </li> <li> sickLeaveBalance: <span>{{leave.balanceSickLeave}}</span> </li> </ul> </div>
内容的提问来源于stack exchange,提问作者StillLearning
相关产品推荐
相关产品推荐

