登录表单中的 IoS 自动填充数据在科尔多瓦应用程序中为空(使用角度)

Posted

技术标签:

【中文标题】登录表单中的 IoS 自动填充数据在科尔多瓦应用程序中为空(使用角度)【英文标题】:IoS Autofill data in login forms is empty in cordova application (using angular) 【发布时间】:2018-11-30 09:55:27 【问题描述】:

Cordova 8 / ios 12 / Angular 6

我有一个带有登录表单的cordova 应用程序。除此之外,一切都运行良好。

在 ios 上,当用户关注表单时,Apple 会提示用户输入保存的密码。 当用户使用此 ios 自动填充功能时,表单不会检测到新值并且数据保持为空。 (但用户可以看到出现在屏幕上的凭据)

这是我的登录表单:

 <form (ngSubmit)="login()" [formGroup]="loginForm">
        <input type="email" formControlName="username" name="username"/>
        <input type="password" formControlName="password" name="password"/>
        <button class="transparent-button primary">Login</button>
    </form>

在我的组件中:

 constructor(
    /* ... */
 ) 
  this.loginForm = formBuilder.group(
    username: ["", Validators.required],
    password: ["", Validators.required]
  );

;

login()
    //this.loginForm.value.username and 
    this.loginForm.value.password stay empty when user 
    autofill

我也尝试过使用模板驱动的表单:同样的问题。 因此,Apple 现在阻止了我的应用程序的发布。 这是 ios/cordova 的已知问题吗?

谢谢

【问题讨论】:

如果您在这里,请花点时间在 github 上为该问题投票,以引起 Angular 团队github.com/angular/angular/issues/30616的关注 【参考方案1】:

对于在 Ionic 5 中遇到此问题的任何人,fix 成功了。我也在常规输入上对此进行了测试(而不是离子输入)。

显然在执行自动填充之后,在没有焦点的输入字段上也会触发Angular(更改)事件,这可以用于设置该表单字段的值。 (如下图):

<input ... (change)="form.controls[fieldName].setValue($event.target.value)">

如评论中所述,即使 Ionic 3 存储库中提到了该修复程序,使用该解决方案的用户(以及我自己)在 Ionic 5 中对其进行了测试。

【讨论】:

【参考方案2】:

FWIW,我遇到了同样的问题,请参阅下面的解决方法。

我正在使用响应式表单,并且在我只有用户名和密码输入的登录表单上遇到了问题。我实现了一个解决方法,我订阅表单上的更改,然后检测本机密码值是否等于更改时的密码表单字段(技术上,更改后 500 毫秒等待自动填充输入密码值)。如果两者不同,我会使用触发表单验证的本机值手动覆盖表单值。

希望这对某人有所帮助!

// login-form.component.ts

import  Component, ViewChild, ElementRef  from '@angular/core';
import  FormGroup, FormBuilder, Validators  from '@angular/forms';

@Component(
  selector: 'app-login-form',
  template: require('./login-form.component.pug')(),
  styleUrls: ['./login-form.component.scss'],
)
export class LoginFormComponent 

  protected loginForm: FormGroup;

  @ViewChild('password') public passwordRef: ElementRef;

  constructor(private _formBuilder: FormBuilder) 
    this.loginForm = this.getForm();

    // NOTE: this hack triggers form validation on iOS autofill
    this.loginForm.valueChanges
      // wait for 500ms to be sure the autofill is finished with the password field
      .debounceTime(500)
      .subscribe((changes) => 
        // manually fetch the value from nativeElement
        let passVal = this.passwordRef.nativeElement.value; //(<htmlInputElement>document.querySelector('[name="password"]')).value;
        // if the value saved in the form is different from the input, manually update it
        if (passVal !== changes.password) 
          this.loginForm.get('password').setValue(passVal);
        
      )
    ;
    // NOTE: this hack triggers form validation on iOS autofill
  

  protected getForm(): FormGroup 
    return this._formBuilder.group(
      username: ['', [
        Validators.required,
        Validators.email,
      ]],
      password: ['', [
        Validators.required,
      ]],
    );
  

  public onSubmit(login: FormGroup) 
    // ...
  

// login-form.component.pug
// NOTE: pug + bootstrap 4

h1 Login
form([formGroup]="loginForm", (ngSubmit)="onSubmit(loginForm)")
  .form-group
    input.form-control(
      formControlName="username",
      name="username",
      type="email",
      placeholder="Username",
      autocomplete="on",
      autocorrect="off",
      autocapitalize="off",
      spellcheck="false",
    )

  .form-group
    input.form-control(
      #password,
      formControlName="password",
      name="password",
      type="password",
      placeholder="Password",
      autocomplete="on",
      autocorrect="off",
      autocapitalize="off",
      spellcheck="false",
    )

  input.mb-3.btn.btn-lg(
    type="submit",
    value="Login",
    [class.btn-outline-primary]="loginForm.valid",
    [class.btn-outline-secondary]="!loginForm.valid",
    [disabled]="!loginForm.valid",
  )

【讨论】:

【参考方案3】:

我可以确认。我在使用 ngModel 使用 Ionic 时遇到了同样的问题,但使用带有 formGroup 的代码也会出现这种情况。

<ion-item>
    <ion-label stacked>Benutzername</ion-label>
    <ion-input [(ngModel)]="username" id="un" type="text" autocomplete="on" autocorrect="on" clearInput="true" clearOnEdit="false"></ion-input>
</ion-item>
<ion-item>
    <ion-label stacked>Passwort</ion-label>
    <ion-input [(ngModel)]="password" id="pw" type="password" autocomplete="on" autocorrect="on" clearInput="true" clearOnEdit="false"></ion-input>
</ion-item>

autocompleteautocorrect 属性 (Ionic Input Attributes) 不会影响 iOS 自动填充功能。

示例应用: 我使用Ionic Getting Started Guide 创建了一个示例应用程序来演示这个问题:

Example Login App

当手动输入凭据时,它们被存储在变量(passwordusername)中,如下图所示: Image 1

在 iOS 设置中设置 AutoFill-credentials 并重新启动模拟器后,我只需单击 Username 字段并单击键盘顶部栏中的“密码”。然后我只是选择了要填写的用户。一切看起来都很好并且填写正确,正如您在Image 2中看到的那样@

然后我点击Login按钮并收到usernamepassword变量的输出,如Image 3

如您所见,我点击并使用自动填充功能的 用户名 字段已将其值同步到其变量。但是密码字段(由于自动填充功能,我从未点击过)不会将其数据同步到其变量。

当我手动点击密码字段并再次使用自动填充功能时,数据与其变量正确同步:Image 4

反之亦然,只需使用自动填充功能进入密码字段。然后密码字段将其值同步到其变量,但用户名字段不会。

【讨论】:

【参考方案4】:

这不是一个很好的解决方案,但它暂时有效,并且苹果接受了我的应用程序。 由于我无法使自动填充正常工作,因此我禁用了它:

我将密码输入更改为文本输入,因此未提出自动填充建议。我还关闭了自动更正、自动大写和自动完成属性。

<form (ngSubmit)="login()" [formGroup]="loginForm">
    <input type="email" formControlName="username" name="username" autocorrect="off" autocapitalize="none" autocomplete="off"/>
    <input type="text" formControlName="password" name="password" autocorrect="off" autocapitalize="none" autocomplete="off" class="passwordInput"/>
    <button class="transparent-button primary">Login</button>
</form>

我在 css 中添加了这个以隐藏输入中的文本并在真实密码输入中模拟项目符号:

.passwordInput 
  -webkit-text-security: disc;

真的在等待真正的解决方案。

【讨论】:

以上是关于登录表单中的 IoS 自动填充数据在科尔多瓦应用程序中为空(使用角度)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 11 应用程序登录屏幕中禁用新密码自动填充功能?

科尔多瓦用buildConfig构建ios,要求我输入密码进行代码签名。

使用 android 应用程序的输入数据自动填充网站表单

jquery 防止自动填充表单

登录表单自动填充,在 iframe 中,在 android 浏览器中不起作用

如何防止在铬浏览器中自动填充同一主机上的表单?