简体   繁体   English

Angular 9 - 如果输入由浏览器自动填充,则表单在 onInit 无效

[英]Angular 9 - Form not valid onInit if input autofilled by Browser

So I noticed a lot of threads about this, but all older and there wasn't an official solution.所以我注意到很多关于这个的线程,但都是旧的并且没有官方的解决方案。 Maybe now there is a solution for this problem.也许现在有解决这个问题的办法。 But basically if you have a form with a username input field, when the page loads the first time, if the browser autofills that value (Because you saved your credentials in your browser), the " login " button will be still disabled because the form is still invalid until the users clicks anywhere for the first time.但基本上,如果您有一个带有用户名输入字段的表单,当页面第一次加载时,如果浏览器自动填充该值(因为您将凭据保存在浏览器中),“ login ”按钮仍将被禁用,因为表单在用户第一次点击任何地方之前仍然无效。

The latest proposed solution I found was using Angular official: AutofillMonitor But it doesnt work:我发现的最新提议的解决方案是使用 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 CODE: 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>

But the form stays invalid even like this, until the users clicks anywhere on the screen, then it gets valid.但是即使这样,表单仍然无效,直到用户单击屏幕上的任意位置,它才会生效。

Is there an official solution for this?有官方解决方案吗?

I do see some approvements that may help, because I don't experience your issue.我确实看到了一些可能会有所帮助的批准,因为我没有遇到您的问题。

First, who do you bind the disabled property of the submit button to the validity of the username field only and not the entire form?首先,您将提交按钮的禁用属性绑定到用户名字段的有效性而不是整个表单的有效性?

Also, I think you ngSubmit is can be a little bit hard to maintain this way, because again, you explicitly use the username field value to pass, while the entire form is available for you in the TS file.另外,我认为您 ngSubmit 可能有点难以以这种方式维护,因为您再次明确使用用户名字段值来传递,而整个表单在 TS 文件中可供您使用。 So the checkAndLoadUserInfo() should not require a parameter.所以checkAndLoadUserInfo()不需要参数。

Then I believe the form build is somewhat 'the old' way to create reactive forms, have you seen that you can create a form control?然后我相信表单构建有点“旧”的方式来创建反应 forms,你看到你可以创建一个表单控件吗? It works the same way:它的工作方式相同:

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

Now what I always do, is create a function called initForm() or something similar and call that from the ngOnInit() .现在我总是做的是创建一个名为initForm()的 function 或类似的东西,然后从ngOnInit()中调用它。 Once that is done, you have an instance of your form.完成后,您就有了表单的一个实例。 You can now easily manipulate form values by setting them like so:您现在可以通过像这样设置它们来轻松地操作表单值:

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

In case you should already be able to get the value from somewhere at the time you init the form, you could also use the first parameter to create the form with the initial value in the desired field.如果您在初始化表单时应该已经能够从某个地方获取值,您还可以使用第一个参数来创建表单,并在所需字段中使用初始值。 Both ways will trigger validation and update the form's state.两种方式都将触发验证并更新表单的 state。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM