2017-01-30 5 views
8

Ich implementiere Login-Seite mit angular reaktiven Formen. Die Schaltfläche "Login" ist deaktiviert, wenn das Formular ungültig ist.Angular 2 und Browser AutoFill

import { Component, OnInit } from '@angular/core'; 
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; 

@Component({ 
    selector: 'signin', 
    templateUrl: './signin.component.html' 
}) 
export class SignInComponent implements OnInit { 
    private signInForm: FormGroup; 

    constructor(private formBuilder: FormBuilder) { } 

    ngOnInit() { 
     this.buildForm(); 
    } 

    private buildForm(): void { 
     this.signInForm = this.formBuilder.group({ 
      userName: ['', [Validators.required, Validators.maxLength(50)]], 
      password: ['', [Validators.required, Validators.maxLength(50)]] 
     }); 

     this.signInForm.valueChanges 
      .subscribe((data: any) => this.onValueChanged(data)); 

     this.onValueChanged(); 
    } 

    private onValueChanged(data?: any) { 
     console.log(data); 
    } 

Also, wenn ich es in Browser zu starten, habe ich vorbelegt Felder „Username“ und „Passwörter“. Und in der Konsole habe ich die Werte "{userName:" [email protected] ", password:" "}" und als Ergebnis ist die Schaltfläche "login" deaktiviert. Aber wenn ich irgendwo auf der Seite klicke trigger onValueChanged und ich sehe '{userName: "[email protected]", Passwort: "123456"}', und die Schaltfläche "Login" ist aktiviert.

Wenn ich im Inkognito-Modus gehe. Ich habe keine vorher ausgefüllten Felder (sie sind leer), aber wenn ich Werte ausfülle (auswähle), dann sehe ich in der Konsole '{userName: "[email protected]", Passwort: "123456"}', und button " Login "ist ohne zusätzlichen Klick aktiviert.

Kann es sich um verschiedene Ereignisse handeln? Autofill und Autocomplete? Und angular arbeitet mit ihnen anders?

Was ist der beste Weg, um es zu lösen? Und warum onValueChanged Funktion wird nur einmal ausgeführt, wenn Browser AutoFill Felder?

Antwort

8

Das Problem im Chrome-Browser: Es erlaubt keinen Zugriff auf den Wert des Kennwortfelds nach der Autofill (vor dem Klicken auf die Seite). Es gibt also zwei Möglichkeiten:

  1. Entfernen der Validierung des Passwortfelds;
  2. Passwortautokomplettierung deaktivieren.
+0

Unglücklicherweise scheint die automatische Passwortvervollständigung nicht zu funktionieren. Versucht alle 3 möglichen Werte: 'autocomplete =" none | false | no "' – Denish

2

Ich konfrontiert das gleiche Problem mit Chrome v58.0.3029.96. Hier ist meine Abhilfe zu halten Validierung und Auto-Vervollständigung:

export class SigninComponent extends UIComponentBase 
{ 
    //-------------------------------------------------------------------------------------------- 
    // CONSTRUCTOR 
    //-------------------------------------------------------------------------------------------- 
    constructor(viewModel: SigninViewModel) 
    { 
     super(viewModel); 

     // Autofill password Chrome bug workaround 
     if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) 
     { 
      this._autofillChrome = true; 
      this.vm.FormGroup.valueChanges.subscribe(
       (data) => 
       { 
        if (this._autofillChrome && data.uname) 
        { 
         this._password = " "; 
         this._autofillChrome = false; 
        } 
       }); 
     } 
    } 

    //-------------------------------------------------------------------------------------------- 
    // PROPERTIES 
    //-------------------------------------------------------------------------------------------- 
    private _password: string; 
    private _autofillChrome: boolean; 

    //-------------------------------------------------------------------------------------------- 
    // COMMAND HANDLERS 
    //-------------------------------------------------------------------------------------------- 
    private onFocusInput() 
    { 
     this._autofillChrome = false; 
    } 
} 

Und in meinem html:

<input mdInput 
     [placeholder]="'USERNAME_LABEL' | translate" 
     [formControl]="vm.FormGroup.controls['uname']" 
     (focus)="onFocusInput()" /> 
[...] 
<input mdInput 
     type="password" 
     [placeholder]="'PASSWORD_LABEL' | translate" 
     [formControl]="vm.FormGroup.controls['password']" 
     (focus)="onFocusInput()" 
     [(ngModel)]="_password" /> 

Ich hoffe, es hilft.

Hinweis: vm wird in UIComponentBase definiert und bezieht sich auf die Ansicht-Modell SigninViewModel meiner Komponente. Die FormGroup Instanz wird im View-Modell definiert, da die Geschäftslogik streng von der Sicht in meiner Anwendung getrennt ist.

UPDATE

Seit v59, so scheint es, dass der Fokus-Ereignis des Eingangs wird ausgelöst, wenn Felder Auto-Vervollständigung. Die obige Problemumgehung funktioniert nicht mehr.Hier ist das aktualisierte Problem umgehen, indem ein Timeout, um festzustellen, ob Felder, die durch die automatische Vervollständigung aktualisiert werden oder durch den Benutzer (ich habe nicht einen besseren Weg gefunden):

export class SigninComponent extends UIComponentBase 
{ 
    //-------------------------------------------------------------------------------------------- 
    // CONSTRUCTOR 
    //-------------------------------------------------------------------------------------------- 
    constructor(viewModel: SigninViewModel) 
    { 
     super(viewModel); 

     // Autofill password Chrome bug workaround 
     if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) 
     { 
      this._autofillChrome = true; 
      setTimeout(
       () => 
       { 
        this._autofillChrome = false; 
       }, 
       250 // 1/4 sec 
      ); 
      this.vm.FormGroup.valueChanges.subscribe(
       (data) => 
       { 
        if (this._autofillChrome && data.uname) 
        { 
         this._password = " "; 
         this._autofillChrome = false; 
        } 
       }); 
     } 
    } 

    //-------------------------------------------------------------------------------------------- 
    // PROPERTIES 
    //-------------------------------------------------------------------------------------------- 
    private _password: string; 
    private _autofillChrome: boolean; 
} 

Und in meinem html:

<input mdInput 
     [placeholder]="'USERNAME_LABEL' | translate" 
     [formControl]="vm.FormGroup.controls['uname']" /> 
[...] 
<input mdInput 
     type="password" 
     [placeholder]="'PASSWORD_LABEL' | translate" 
     [formControl]="vm.FormGroup.controls['password']" 
     [(ngModel)]="_password" /> 
-1

ich habe ein funtion

formIsValid(): boolean{ return this.form.valid; }

und als die Schaltfläche hinzu:

Es ist für mich gearbeitet

0

Aus Gründen der Vollständigkeit: Ich habe ein nicht-reaktives Login-Formular habe. .

<form name="loginForm" role="form" (ngSubmit)="onLoginSubmit()"> 
    <input name="username" #usernameInp> 
    <input type="password" name="password" #passwordInp> 
    <button type="submit">Login</button> 
</form> 

Wenn ich [(ngModel)]="username" verwenden, die Variable username der zugehörigen Komponente nicht in, wenn der Browser autofill Funktionalität Tritte bevölkert erhalten

Deshalb habe ich stattdessen mit ViewChild arbeiten:

@ViewChild('usernameInp') usernameInp: ElementRef; 
@ViewChild('passwordInp') passwordInp: ElementRef; 
... 
onLoginSubmit() { 
    const username = this.usernameInp.nativeElement.value; 
    const password = this.passwordInp.nativeElement.value; 
    ... 

Auf diese Weise kann ich auf die vom Browser bereitgestellten Werte zugreifen, sobald der Benutzer auf Login klickt.