Angular 11 中的 ngOnIt() 中的属性未获取值

Properties not getting value in ngOnIt() in Angular 11

我正在使用 LeaveService 中的 Api 从数据库获取数据。要获取数据,使用的方法是 LeaveService 中的 applyLeaveGet(id:string)。此方法提供某些值,例如来自数据库的 joiningDate。 我正在使用反应形式的 Angular Material UI。

问题是即使 leave 实例正在获取数据,但是在 ngOnInt() 中,属性没有获取值.ngOnInt() 确实被触发.例如,我收到加入日期未定义的错误。 我该如何解决这个问题。谢谢你的帮助

LeaveService : applyLeaveGet(id:string) 方法

applyLeaveGet(id:string){
    return this.http.get<Leave>('https://localhost:44330/api/leave/ApplyLeaveGet/'+ id);
  }

ApplyLeave 组件

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
    ) {

     leaveService.applyLeaveGet(authenticationService.getUserId())
      .subscribe(data =>
        this.leave = data
       );

    // Set the minimum to January 1st 20 years in the past and December 31st a year in the future.
    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":['']
  });
  
  }


  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);
    formData.append('currentDate', this.form.value.fullName);
    formData.append('joiningDate', this.form.value.fullName);
    formData.append('fromDate', this.form.value.fullName);
    formData.append('tillDate', this.form.value.fullName);
    formData.append('leaveType', this.form.value.fullName);
    formData.append('duration', this.form.value.fullName);
    formData.append('reason', this.form.value.fullName);
    formData.append('balanceAnnualLeave', this.form.value.fullName);
    formData.append('balanceSickLeave', this.form.value.fullName);
    formData.append('balanceAnnualLeave', this.form.value.fullName);
    formData.append('File', this.selectedFile);
  }
}

这是html

<p>add-edit-leave works!</p>
<div class="container">
    <form class="form-container" [formGroup]="form" (ngSubmit)="onSubmit()">
        <mat-card>
            <mat-card-header>
                <mat-card-title>Apply Leave</mat-card-title>
            </mat-card-header>
            <mat-card-content>
                <div class="row">
                    <div class="col-md-6">
                        <mat-form-field class="full-width">
                            <mat-label>Today's Date</mat-label>
                            <input formControlName="currentDate" type="date" class="form-control" matInput placeholder="Today's Date" readonly > 
                        </mat-form-field>
                    </div>
                    
                    <div class="col-md-6">
                        <mat-form-field class="full-width">
                            <mat-label>Joining Date</mat-label>
                            <input formControlName="joiningDate" type="datetime" class="form-control" matInput  placeholder="Joining Date">
                        </mat-form-field>
                    </div>
                </div>
                <!--Date Requested For-->
                <div class="row">
                    <div class="col-md-6">
                        <mat-form-field class="full-width" appearance="fill">
                            <mat-label>From Date</mat-label>
                            <input matInput formControlName="fromDate" [min]="minDate" [max]="maxDate"
                                [matDatepicker]="picker">
                            <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
                            <mat-datepicker #picker></mat-datepicker>
                        </mat-form-field>
                    </div>
                    <div class="col-md-6">
                        <mat-form-field class="full-width" appearance="fill">
                            <mat-label>Till Date</mat-label>
                            <input matInput formControlName="tillDate" [min]="minDate" [max]="maxDate"
                                [matDatepicker]="pickerTillDate">
                            <mat-datepicker-toggle matSuffix [for]="pickerTillDate"></mat-datepicker-toggle>
                            <mat-datepicker #pickerTillDate></mat-datepicker>
                        </mat-form-field>
                    </div>

                </div>
                <!--Leave Type Duration(dropdown box)-->
                <div class="row">
                    <div class="col-md-6">
                        <mat-form-field class="full-width" appearance="fill">
                            <mat-label>Leave Type</mat-label>
                            <select formControlName="leaveType" matNativeControl id="mySelectId">
                                <option value="" disabled selected></option>
                                <option value="Annual Leave">Annual Leave</option>
                                <option value="Sick Leave">Sick Leave</option>
                            </select>
                        </mat-form-field>
                    </div>
                    <div class="col-md-6">
                        <mat-form-field class="full-width" appearance="fill">
                            <mat-label>Duration</mat-label>
                            <select formControlName="duration" matNativeControl id="mySelectId">
                                <option value="" disabled selected></option>
                                <option value="Full Day ">Full Day</option>
                                <option value="First Half Day">First Half Day</option>
                                <option value="Second Half Day">Second Half Day</option>
                            </select>
                        </mat-form-field>
                    </div>
                </div>
                <!--Reason-->
                <div class="row">
                    <div class="col-md-12">
                        <mat-form-field class="full-width">
                            <mat-label>Reason</mat-label>
                            <input formControlName="reason" matInput placeholder="Reason">
                        </mat-form-field>
                    </div>
                </div>
 
                <div class="row">
                    <div class="col-md-6">
                        <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>
                </div>
                <!--Submit-->
                <mat-card-actions>
                    <button mat-stroked-button type="submit>Basic</button>
                </mat-card-actions>
            </mat-card-content>
        </mat-card>

    </form>
</div>

在您的问题的当前版本中,您似乎没有在 OnInit 的表单中使用 this.leave 中的任何设置值。根据您的问题描述和其余代码,我认为您的问题是 LeaveService 在构造函数中的异步调用。由于它是异步代码,因此在调用和执行 ngOnInit 之前可能无法完成,因此会出现有关未定义值的错误消息。您必须等到 HTTP 调用完成才能访问数据。

由于您不应在构造函数中执行可能较长的 运行 HTTP 调用,因此我建议将该部分移动到 OnInit 中。所有不长运行和异步的都可以在构造函数中执行。您的代码可以这样重构:

constructor(private fb: FormBuilder,
  private http: HttpClient,
  private leaveService : LeaveService,
  private route : ActivatedRoute,
  private authenticationService: AuthenticationService
) {
    // Set the minimum to January 1st 20 years in the past and December 31st a year in the future.
    const currentYear = new Date().getFullYear();
    this.minDate = new Date(currentYear - 20, 0, 1);
    this.maxDate = new Date(currentYear + 1, 11, 31);

    this.form = this.fb.group({
        "currentDate": new FormControl(this.currentDate.toISOString().split("T")[0]),
        "joiningDate": [''],
        "fromDate": [''],
        "tillDate": [''],
        "leaveType": [''],
        "duration": [''],
        "reason": [''],
        "filePath": ['']
    });
}

ngOnInit() {
    leaveService.applyLeaveGet(authenticationService.getUserId())
      .subscribe(data =>
        {
            this.leave = data;

            // now data is here and can be used to set initial form values, example:
            this.form.get('leaveType').setValue(this.leave.Type);
        }
    );
}