反应形式 - 使用 disabled 属性时的警告

Reactive forms - Warning when using the disabled attribute

我想在我的一个表单中禁用 select 框,而其中 select 没有任何内容,直到从服务器返回此 select 框的数据。我需要这样做,因为 select 框中显示的数据取决于 select 在另一个 select 框中编辑的内容。每当在另一个 select 框中输入 select 内容时,我需要从服务器加载相应的选项。要在没有可用数据时禁用 select 框,我使用如下禁用属性:

<mat-select formControlName="formId" [disabled]="formNames.length === 0">
  <mat-option
    *ngFor="let formName of formNames"
    [value]="formName.id"
  >
    {{ formName.formName }}
  </mat-option>
</mat-select>

然后我像这样订阅了另一个 select 框的 valueChanges 事件:

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

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

  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)
  });

我不明白这个警告是什么意思,建议的解决方案也没有真正帮助我,因为我不想简单地将 disabled 属性 设置为 true。在没有可用的表单名称的情况下,我实际上应该做什么来实现禁用 select 框的预期行为?还是我的方法很好,我应该忽略这个警告?

由于您使用的是反应式表单,这意味着您在控制表单,这与 Angular 为您完成所有工作的模板表单不同。

将控件作为属性禁用,您要求 Angular 为您做这件事,因此 Angular 提醒您一切尽在您的掌控之中。

报错提示你在创建控件时如何设置禁用状态,但如果以后需要enable/disable,则需要使用控件的“启用”和“禁用”功能.

this.createForm.controls.formTypeId.disable()
or
this.createForm.controls.formTypeId.enable()

Angular 告诉您您正在混合两种不同类型的表单方法。一种是template-driven,另一种是反应形式。当您使用反应式表单时 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;
  });
});

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

此外,您正在使用嵌套订阅。即一个 subscribe 在另一个 subscribe 中,这是一种不好的做法,应该避免。我建议您查看 switchMapmergeMap 等满足您的 use-case 的 RxJs 映射。例如,如果你想在新事件到来时取消之前的订阅,你可以使用 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;
      });

您收到的警告是因为在 Angular 中还有另一种方法可以做到这一点。我假设在你的 .ts 文件中你有这样的东西:

ngOnInit(): void {
this.createForm = this.fb.group({
formName: [{value: this.formName, disabled: this.formNames.length === 0}] 
}