反应式表单 - 使用禁用属性时发出警告

Chr*_*ris 2 angular angular-reactive-forms angular12

我想禁用其中一个表单中的选择框,而在从服务器返回该选择框的数据之前,其中没有任何内容可供选择。我需要这样做,因为选择框中显示的数据取决于另一个选择框中选择的内容。每当在另一个选择框中选择某些内容时,我需要从服务器加载相应的选项。要在没有可用数据的情况下禁用选择框,我使用了如下所示的禁用属性:

<mat-select formControlName="formId" [disabled]="formNames.length === 0">
  <mat-option
    *ngFor="let formName of formNames"
    [value]="formName.id"
  >
    {{ formName.formName }}
  </mat-option>
</mat-select>
Run Code Online (Sandbox Code Playgroud)

然后我订阅了valueChanges另一个选择框的事件,如下所示:

this.createForm.controls.formTypeId.valueChanges.subscribe((value: number) => {
  this.formsService.getFormNames(value).subscribe((formNames) => {
    this.formNames = formNames;
  });
});
Run Code Online (Sandbox Code Playgroud)

虽然这似乎工作得很好,但我不断在浏览器控制台中收到以下警告:

  It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
  when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
  you. We recommend using this approach to avoid 'changed after checked' errors.

  Example:
  form = new FormGroup({
    first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
    last: new FormControl('Drew', Validators.required)
  });
Run Code Online (Sandbox Code Playgroud)

我不明白这个警告意味着什么,建议的解决方案也并不能真正帮助我,因为我不想简单地将属性设置disabledtrue. 在没有可用的表单名称的情况下,我实际上应该做什么来实现禁用选择框的所需行为?或者我的方法很好,我应该忽略这个警告?

Has*_*oin 5

Angular 告诉您,您正在混合两种不同类型的表单方法。一种是模板驱动的,另一种是反应式的。当您使用反应式表单时,角度警告您应该使用反应式方法来禁用表单控件,而不是使用 HTML 属性[disabled]

在您的用例中,您可以根据订阅块中的长度来启用或禁用该字段,该字段应如下所示:

this.createForm.controls.formTypeId.valueChanges.subscribe((value: number) => {
  this.formsService.getFormNames(value).subscribe((formNames) => {
    if(formNames.length > 0){
        this.createForm.controls.formControlName.enable();
    } else {
        this.createForm.controls.formControlName.disable()
    }
    this.formNames = formNames;
  });
});
Run Code Online (Sandbox Code Playgroud)

阅读本文以获得更好的见解:https://indepth.dev/posts/1474/disable-form-controls-using-forms-api-or-html-attributes

此外,您正在使用嵌套订阅。即一个subscribe在另一个subscribe,这是一种不好的做法,应该避免。我建议您研究 RxJs 映射,例如switchMapmergeMap,无论哪个满足您的用例。例如,如果您想在新事件发生时取消先前的订阅,您可以使用switchMap

this.createForm.controls.formTypeId.valueChanges
      .pipe(
          switchMap((value: number) => {
              return this.formsService.getFormNames(value);
          })
      )
      .subscribe(formNames => {
          if (formNames.length > 0) {
              this.createForm.controls.formControlName.enable();
          } else {
              this.createForm.controls.formControlName.disable();
          }
          this.formNames = formNames;
      });
Run Code Online (Sandbox Code Playgroud)