Angular 2 and browser autofill Angular 2 and browser autofill typescript typescript

Angular 2 and browser autofill


The problem in Chrome browser: it does not allow access to the value of the password field after autofill (before user click on the page). So, there are two ways:

  1. remove validation of the password field;
  2. disable password autocompletion.


I found out that you can use autocomplete="new-password"

As is decribed here

This way your password fields will not be autofilled at all, and that was my case.There are many others autocomplete attributes available in the link above.


I faced the same issue with Chrome v58.0.3029.96. Here is my workaround to keep validation and autocompletion:

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;    }}

And in my 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" />

I hope it helps.

Note: vm is defined in UIComponentBase and refers to the view-model SigninViewModel of my component. The FormGroup instance is defined in the view-model as the business logic is strictly separated from the view in my application.

UPDATE

Since v59, it seems that the input's focus event is fired when auto-completing fields. So the above workaround doesn't work anymore. Here is the updated workaround, using a timeout to determine if fields are updated by the auto-completion or by the user (I haven't found a better way):

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;}

And in my 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" />