【问题标题】:Angular reactive forms - does pristine reset when the user reverts the UI changes to original values?角度反应形式 - 当用户将 UI 更改恢复为原始值时,原始值是否会重置?
【发布时间】:2020-12-08 19:19:21
【问题描述】:

我只想在表单输入发生变化时启用表单中的提交按钮。

提交按钮应在表单控件值未更改时禁用。

我尝试使用FormGroup.pristine 标志来启用/禁用提交按钮。

启用按钮效果很好。

但是,当 UI 中的值更改回其原始值时,它不会重置为 true

组件代码:

import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';

@Component({
  selector: 'app-registration-form',
  templateUrl: './registration-form.component.html',
  styleUrls: ['./registration-form.component.scss']
})
export class RegistrationFormComponent {
  public registrationForm;
  public formValues = {
      gender: 1,
    };

  constructor(private formBuilder: FormBuilder) {
    this.registrationForm = formBuilder.group(this.formValues);
  }

  onSubmit(formData) {
    console.log('Your form is submitted', formData);
    this.registrationForm.reset(this.formValues);
  }
}
<form class="registration-form" [formGroup]="registrationForm" (ngSubmit)="onSubmit(registrationForm.value)">
  <div>
    <label for="gender">Gender</label>
    <select id="gender" formControlName="gender">
      <option value=1>female</option>
      <option value=2>male</option>
      <option value=3>do not specify</option>
    </select>
  </div>
  <input type="submit" [disabled]="registrationForm.pristine">
</form>

默认情况下,选择框中选择“女性”选项。

当用户将其更改为“男性”时,例如,提交按钮被启用。

现在当用户再次选择“女性”时,提交按钮不会被禁用。

用户必须单击提交按钮才能恢复原始状态并禁用按钮。

当用户将选择框的值改回默认值时,如何在不点击提交按钮的情况下重置为原始状态?

Angular 版本:8.2.14

更新

遗憾的是,当用户将 UI 更改为默认值时,Angular 似乎并没有将表单状态更改为原始状态。

因此我们必须编写代码来进行数据比较并将表单标记为原始状态。

【问题讨论】:

  • 可以订阅ValueChanges this.registrationForm.valueChanges.subscribe(x => {})

标签: angular angular8


【解决方案1】:

当数据变回 defaultValue 时,您可以使用 markAsPristine 方法将原始状态设置为 true,如下所示:

ngOnInit() {
    const defaultValue = this.registrationForm.value;
    this.registrationForm.valueChanges
      .pipe(debounceTime(200))
      .subscribe(value => {
        if (JSON.stringify(defaultValue) == JSON.stringify(value)) {
          this.registrationForm.markAsPristine();
        }
      });
  }

【讨论】:

  • 您好 Chellappan,谢谢您的回答。与 Minal 的回答类似,您的回答清楚地表明 angular 默认情况下不会处理它,我们需要处理它。通常一个表单会有多个值。所以我们必须编写一个对象比较逻辑或使用像 lodash 这样的库作为 Minal 的答案。不幸的是,从角度来看,这令人失望。
  • 确实如此,由于FormGroup提供valueChanges API作为Observable,如果你有很多文本输入,我们可以使用rxjs debounce操作符来减少markAsPristine方法调用的次数。
  • 您能否更改您的代码示例以订阅 FormGroup 而不仅仅是性别控制?我相信这是更适合我的问题的方法。
  • 我已经更新了你现在可以检查一下吗:你可以使用 loadash 或其他方式来检查对象比较,而不是使用 JSON.strinfy 示例:stackblitz.com/edit/angular-ivy-1itbpo?file=src/app/…
  • 谢谢 Chellappan,我可以从 Minal 的回答中获取 lodash 比较的想法,而不是 JSON.stringify。但总的来说,由于您建议使用valueChanges observable 和markAsPristine 采取更角度的方法,我会将您的答案标记为已接受。
【解决方案2】:

如果没有任何更改,您可以创建一种返回 true 或 false 的方法来禁用提交按钮。

假设您有一些用于存储表单输入的对象。

函数参考以下代码:

oldObj = _.cloneDeep(this.obj)
dataChanged(){
 return !_.isEqual(this.oldObj, this.obj)
}

并在 html 中添加以下行

<input type="submit" [disabled]="!hasChanged()">

【讨论】:

  • 感谢您的回答。我期待 Angular 默认提供此功能,因此我们不必编写此比较逻辑。所以我试图避免这种代码。可悲的是,一旦用户更改输入,angular 会将表单状态设置为dirty,并且即使用户恢复他的 UI 更改也不会更改它。
  • 是的,Angular 没有直接提供其他方法来处理这个问题。
  • 嗨 Minal,我会接受 Chellappan 的回答,但我喜欢你的 lodash 比较想法,所以会支持你的回答。
猜你喜欢
  • 2017-01-31
  • 1970-01-01
  • 2013-07-21
  • 2017-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
相关资源
最近更新 更多