【问题标题】:Angular 9 - Form not valid onInit if input autofilled by BrowserAngular 9 - 如果输入由浏览器自动填充,则表单在 onInit 无效
【发布时间】:2020-11-11 15:40:12
【问题描述】:

所以我注意到很多关于此的线程,但都是较旧的并且没有官方解决方案。 也许现在有解决这个问题的办法。 但基本上,如果您有一个带有用户名输入字段的表单,当页面第一次加载时,如果浏览器自动填充该值(因为您将凭据保存在浏览器中),“login”按钮仍将被禁用,因为在用户第一次点击任意位置之前,表单仍然无效。

我发现的最新提议的解决方案是使用 Angular 官方:AutofillMonitor 但它不起作用:

 @ViewChild("email") inputEl: ElementRef;

constructor(
    private formBuilder: FormBuilder,
    private _autofill: AutofillMonitor
  ){
    this.emailForm = this.formBuilder.group(
      {
        userLogin: [
          "",
          {
            validators: [Validators.required],
          },
        ],
        password: [
          "",
          {}
        ]
      }
    );
  }

ngAfterViewInit() {
    this._autofill.monitor(this.inputEl)
    .subscribe(e => {
        if (e.isAutofilled) {
          // this works, the code gets in here onInit
        this.forceValidityCheck();
        }
      }
    );
  }

forceValidityCheck() {
    this.emailForm.controls["userLogin"].updateValueAndValidity();
  }

HTML 代码:

<ng-container>
      <form [formGroup]="emailForm" (ngSubmit)="checkAndLoadUserInfo(emailForm.get('userLogin').value)">
      <mat-form-field appearance="standard" class="standardInputField">
        <mat-label translate>enter_email.username</mat-label>
        <input matInput formControlName="userLogin" #email type="email" placeholder="name@example.org" (keyup.enter)="checkAndLoadUserInfo(emailForm.get('userLogin').value)" autofocus autocomplete="username">
        <label class="pswValidationLabels" *ngIf="emailForm.get('userLogin').hasError('doesNotExist')" translate>
          enter_email.unknown_user
          </label>
      </mat-form-field>

      <mat-form-field appearance="standard" class="hiddenFormField">
      <input matInput type="password" autocomplete="current-password">
      </mat-form-field>

      <div>
        <button [disabled]="!emailForm.get('userLogin').valid" mat-raised-button>
        </button>
      </div>
    </form>
    </ng-container>

但是即使这样,表单仍然无效,直到用户点击屏幕上的任意位置,它才会生效。

这个有官方解决方案吗?

【问题讨论】:

  • 也分享html代码
  • 如果你在forceValidityCheck之后打印this.emailForm.valid,它会说什么?
  • @SRana 添加了 html 代码
  • @MarcellKiss“无效”
  • 试试这个[disabled]="emailForm.invalid &amp;&amp; emailForm.touched"

标签: angular forms autofill


【解决方案1】:

我确实看到了一些可能有帮助的批准,因为我没有遇到您的问题。

首先,您将提交按钮的禁用属性绑定到用户名字段的有效性而不是整个表单的有效性?

另外,我认为您的 ngSubmit 可能有点难以以这种方式维护,因为您再次明确地使用用户名字段值来传递,而整个表单在 TS 文件中可供您使用。所以checkAndLoadUserInfo() 应该不需要参数。

那么我相信表单构建在某种程度上是创建响应式表单的“旧”方式,您是否看到可以创建表单控件?它的工作方式相同:

this.newGameForm = new FormGroup({
    userLogin: new FormControl('', [
        Validators.required
    ])
});

现在我总是做的是创建一个名为initForm() 或类似的函数,然后从ngOnInit() 调用它。完成后,您就有了表单的一个实例。您现在可以通过如下设置轻松操作表单值:

this.formName.patchValue({ userLogin: 'new value'});

如果您在初始化表单时应该已经能够从某个地方获取值,您还可以使用第一个参数来创建表单,并在所需字段中使用初始值。两种方式都会触发验证并更新表单的状态。

【讨论】:

  • 我之前已经尝试过使用 patchValue,因为我在另一个线程中找到了它,但它不能正常工作。关于绑定到用户名的有效性,我这样做是因为这里用户没有输入密码,它是一个隐藏字段,他只输入用户名,通过 API 调用检查其有效性,只有这样,如果用户名存在于数据库中,他被要求输入密码!无论如何,我按照用户的建议解决了它,方法是在 Disabled 属性中添加:“&& this.emailForm.touched”!那么,使用表单构建的“旧方式”与使用您的语法之间是否有真正的区别?
  • 我不确定你的第二个问题,但它可以让你不必注入表单构建器。您仍然可以在整个表单上应用验证,因为您没有在密码字段上定义任何验证规则。只要所有字段都有效,表单就会生效,并且由于密码字段没有验证规则,所以只要用户名字段有效,表单就会生效。
  • 我为您创建了一个 stackblitz,以便您可以看到它的实际效果:stackblitz.com/edit/angular-ivy-ln2git
猜你喜欢
  • 2017-04-09
  • 1970-01-01
  • 2017-06-15
  • 2012-02-01
  • 2021-02-25
  • 2013-04-04
  • 2018-12-04
  • 2018-10-29
  • 1970-01-01
相关资源
最近更新 更多