Angular 7 表单 ExpressionChangedAfterItHasBeenCheckedError - 带有条件输入字段

Angular 7 Form ExpressionChangedAfterItHasBeenCheckedError - with conditional Input Field

在我的 Angular 7 表单之一中,我试图根据其他用户输入值制作输入字段。这是我的 html 代码。

div>
     <form [formGroup]="UserForm" #UserAdd="ngForm">               
        <mat-form-field>
            <mat-label>Gender</mat-label>
            <mat-select [(value)]="gentype" [formControl]="gendertype" required>
                <mat-option value="Male">Male</mat-option>
                <mat-option value="Female">Female</mat-option>
            </mat-select>
            <mat-error *ngIf="gendertype.hasError('required')">
                Gender is required.
            </mat-error>
        </mat-form-field>       
        <mat-form-field>
            <mat-label>Enrolled</mat-label>
            <mat-select [(value)]="enrol" [formControl]="enrolled" required>
                <mat-option value="No">No</mat-option>
                <mat-option value="Yes">Yes</mat-option>
            </mat-select>
        </mat-form-field>
        <mat-form-field class="form-element" *ngIf="enrol=='Yes'">
            <mat-label>User Preference</mat-label>
            <input matInput [placeholder]="gentype=='Male' ? 'Chicago' : 'Milan'" formControlName="preference" [required]="true" autocomplete="off">
            <mat-error *ngIf="preference.touched && !preference.required">
                Preference is required.
            </mat-error>
        </mat-form-field>
    </form>
    <button mat-raised-button color="primary" type="button" (click)="Save();"[disabled]="!UserAdd.form.valid">SAVE</button>
</div>

Component.ts代码。

private UserForm: FormGroup; 
ngOnInit() {
    this.createForm()   
  }
createForm() {
    console.log('in createForm')
    this.UserForm = new FormGroup({
            gendertype: new FormControl(), 
            enrolled: new FormControl('No'),
            preference: new FormControl('')
    })
  }  
get gendertype() { return this.UserForm.get('gendertype') }
get enrolled() { return this.UserForm.get('enrolled') }
get preference() { return this.UserForm.get('preference') }

我面临的问题是,当用户 select "enrol-No" 表单处于无效状态并且“保存”按钮被禁用时。我想在拍摄时将首选项输入为 "required"。如果用户 select "enrol-Yes",我得到错误

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'disabled: false'. Current value: 'disabled: true'. 

请提出我错误的地方以及处理这种情况的好方法。

不要使用 [formControl]='gendertype 绑定控件,而是使用 formControlName='gendertype'。这将使用不依赖于您创建的 get 函数的表单控件实例进行绑定。这就是触发 expressionChanged 错误的原因。

如果这没有帮助,请创建一个示例 stackblitz 以尽量减少复制。

您收到此错误是因为您需要在首选项表单控件上绑定属性。使用反应式表单时,您必须使用验证器函数将验证包含在表单控件中。

您可以在 FormControl 上使用禁用 属性 来动态禁用和启用 formControl。

component.ts

createForm() {
    console.log('in createForm')
    this.UserForm = new FormGroup({
            gendertype: new FormControl(), 
            enrolled: new FormControl('No'),
            preference: new FormControl({value: '', disabled:true}, Validators.required)
    })
}  

在模板端你可以检查用户是否注册,使用注册控制值属性

component.html

<mat-form-field class="form-element" *ngIf="enrolled.value=='Yes'">
            <mat-label>User Preference</mat-label>
            <input matInput [placeholder]="gentype=='Male' ? 'Chicago' : 'Milan'" formControlName="preference"  autocomplete="off">
            <mat-error *ngIf="preference.touched && !preference.required"> 
                Preference is required.
            </mat-error>
   </mat-form-field>

最后监听已注册控件的 valueChanges 以动态禁用和启用首选项表单控件

component.ts

this.createForm();
    (this.enrolled as FormControl).valueChanges.subscribe(hasEntrolled=>{
     if(hasEntrolled === 'Yes'){
        (this.preference as FormControl).enable();
     }else{
          (this.preference as FormControl).disable();
     }
    });

Example