Disable autofill/autocomplete with angular form and chrome
Mia Lopez
I have a simple form where I need disable autofill/autocomplete with angular form.
I have search on StackOverflow, but I didn´t find a solution.
I have used autocomplete="off" or autocomplete="false" but the autocomplete is never disabled.
Sometimes the autocomplete is disabled temporarily when I load a page. But, after some time after, when I reload the page the problem appears again.
//markup from image above
<input type="text" capitalize-full="" ng-model="user.ENDERECO" required="" placeholder="Digite seu endereço" autocomplete="off" name="street">//markup sample
<form name="regForm" autocomplete="false" novalidate> <input type="text" name="cpf" ng-model="user.CPF" placeholder="Digite seu CPF" required autocomplete="false" >
</form> 6 21 Answers
In April 2018: Setting autocomplete="off" on the form itself worked for me (tested on Chrome). Setting this attribute on individual elements did not work.
Simply put autocomplete="new-feildName" on html control
Example :
<input autocomplete="new-phone" formControlName="phone" name="phone" type="text"> 2 The autocomplete="off" is effectively respected by Chrome, but what you're experiencing is the Chrome autofill functionality that takes over, ignoring autocomplete="off": .
In the past, many developers would add autocomplete="off" to their form fields to prevent the browser from performing any kind of autocomplete functionality. While Chrome will still respect this tag for autocomplete data, it will not respect it for autofill data.
I did some test and from what I see here Chrome igonores the autocomplete="off" when it can map the fieldname to one of it's autofill properties. This will work <input type="text" name="somethingAutofillDoesntKnow" autocomplete="off" />, but for this fieldName Autofill will show up <input type="text" name="firstName" autocomplete="off" />.
One workaround is to put an unknown value in the autocomplete, e.g. autocomplete="doNotAutoComplete". When testing this it worked for me most of the time, but for some reason didn't work anymore afterwards.
My advise is not to fight against it and use it's potential by properly using the autocomplete attribute as explained here:
On Chrome, specifying autocomplete="off" didn't work for me. However, autocomplete="disabled" worked properly.
You can test and evaluate using this page: (try changing the off to disabled using your browser).
Goodluck!
Try <input autocomplete="off" type="search"> it worked for me
Considering that chrome ignores the autocomplete="off" attribute value in case of credentials/address/credit card data type, as a workaround I have used this directive successfully solving my problem:
import { Directive, ElementRef, OnInit } from '@angular/core';
@Directive({ selector: '[autocomplete]'
})
/** * Alterates autocomplete="off" atribute on chrome because it's ignoring it in case of credentials, address or credit card data type. */
export class AutocompleteDirective implements OnInit { private _chrome = navigator.userAgent.indexOf('Chrome') > -1; constructor(private _el: ElementRef) {} ngOnInit() { if (this._chrome) { if (this._el.nativeElement.getAttribute('autocomplete') === 'off') { setTimeout(() => { this._el.nativeElement.setAttribute('autocomplete', 'offoff'); }); } } }
} 1 In Angular, this directive worked for me. Using the autocomplete="off" should have solved the issue, but it seems as though the DOM rendering sequence prevents that unless you use a timeout.
Additionally, if you use something like mat-form-field and autocomplete is generated based on the unique names, you can add a Zero-width non-joiner anywhere after the first character and before the last character.
import { Directive, ElementRef, OnInit, Renderer2, AfterViewInit } from '@angular/core'
@Directive({ selector: '[NoAutocomplete]',
})
export class NoAutocompleteDirective implements AfterViewInit { constructor(private renderer: Renderer2, private _el: ElementRef) {} ngAfterViewInit() { setTimeout(() => { const inputs = Array.prototype.slice.call(this._el.nativeElement.querySelectorAll('input')) inputs.map((e, i) => { this.renderer.setAttribute(e, 'autocomplete', 'off') }) // If you're using mat-form-field const labels = Array.prototype.slice.call( this._el.nativeElement.querySelectorAll('.mat-form-field-label') ) labels.map((l, i) => { l.innerHTML = l.innerHTML.replace( l.textContent, l.textContent.substring(0, 1) + '‌' + l.textContent.substring(1) ) }) }, 0) }
} 0 In my case, for email and password fields, autocomplete="off" [attribute] is not working accordingly. So, I have used autocomplete="new-email" and autocomplete="new-password" for email and password fields, which is disabling auto filling. On the other hand use of autocomplete="cc-name" for both email and password fields is also working fine.
E.g, 1:
<input type="email" autocomplete="new-email" formControlName="email" />
<input type="password" autocomplete="new-password" formControlName="password" />E.g, 2:
<input type="email" autocomplete="cc-name" formControlName="email" />
<input type="password" autocomplete="cc-name" formControlName="password" /> 1 I would assume the option is only needed on the input tag.
<input name="q" type="text" autocomplete="off"/> 2 autocomplete="off" alone might not do the job. Chrome tries to guess the type of input in absence of a name attribute, and messes up sometimes. The trick that worked for me is to add a name attribute.
<mat-form-field> <mat-label>Track</mat-label> <input name="track" matInput autocomplete="off" [(ngModel)]="track">
</mat-form-field>Hope this helps someone 🙏
For me neither autocomplete="off" nor changing the name attribute worked alone.
But together (changing autocomplete to a random value - one that is not used by any other site and name attribute to something different) it worked.
I guess Chrome is trying to be too smart and guessing based on autocomplete value and name value.
Here is an example of my working solution:
<input matInput formControlName="email" autocomplete="noac" type="email" name="emailnoauto" placeholder="E-Mail" />It's not nice, but it works.
autocomplete="off"/autocomplete="false"/autocomplete="disabled" didn't work for me.
However, setting autocomplete="new-fieldname" worked for me in individual fields. But it won't work with the form element.
Chrome version:81.0.4044.122
<input type="text" name="first_name" autocomplete="new-name" required> Long story short, there is no one solution, only a workaround depending on the browser and what are you trying to do. (This answer is for Chrome and Edge)
First things first
autocomplete is not a boolean field, instead, it is a field that can have many values, depending on the type of field, you can look here for more info
Chrome and Edge behave differently even though Edge is using Chromium
I am using Angular, but you can solve it for any other framework, in my case I had to use ngAfterViewInit() and then a setTimeout() of 0.5 seconds
My original issue was using the google address search service (originally I thought that was my only issue)
Solving the problem
set the form with autocomplete=off, hopefully, one day this should be enough, but for some reason, Chrome thinks otherwise
loop thru all the inputs and set autocomplete="off" (this should also be the solution in the distant future)
Set address-form-google-search input to autocomplete="nope" (or anything else other than a real value)
Set all addresses fields to "nope" you can look at the function setAddressFields()
Although "nope" works for the address fields, in Edge, there are also custom fields you can save (look in settings Addresses), for this reason, I had to do a workaround, in my case, nothing worked, so I had to hack and use a valid autocomplete value (in this case I used additional-name), and I was lucky that Edge accepted that value and didn't have it saved in the settings as an option
After the Address fields were fixed, then I had the issue that Chrome/Edge remembers what you typed in the field, even if it's not an address, so I had to rename the name with a random value
I hope I didn't beat around the bushes too much, but if you haven't had all these issues is because you have not tested enough. Please go to Chrome/Edge and open Settings and add Address fields there (make sure is enabled), also add credit card information, and you will see how all the previous answers are just partial solutions. So far everything is looking good, if QA finds another issue I will come back and edit this post.
Note: before using additional-name, I was going down the list and cc-number seems to be working fine, tested everywhere and it was the same solution for Edge and Chrome until I realized that cc-number is for Credit Cards, and sadly I have that in my application, so once I added a credit card, I was back to square 1. So additional-name is working for me so far, but who knows in the future :)
ngAfterViewInit() { setTimeout(() => { // turn off any input field document.querySelectorAll('input').forEach((element) => { element.setAttribute('autocomplete', 'off'); }); document.querySelectorAll('textarea').forEach((element) => element.setAttribute('autocomplete', 'off')); // this code disable address fields document.querySelector('#address-form-google-search').setAttribute('autocomplete', 'nope'); if (/Edg/.test(navigator.userAgent)) { this.setAddressFields('additional-name'); } else { this.setAddressFields('nope'); } // other fields may still save the information by looking at name, here we randomize the name const random = Math.random(); document.querySelectorAll('input').forEach((element) => { if (element.id !== 'address-form-google-search') { element.setAttribute('name', element.name + '_' + random); } }); }, 500); } autocomplete="off" not working you just need to put something like this.
<input autocomplete="new-username" formControlName="username" name="username" type="text">instead of:
<input autocomplete="off" formControlName="username" name="username" type="text"> I have the same problem, for me the problem was LastPass. Once disconnected everything works just fine. And two weeks of code rewriting to find the bug. Of course none that I find on internet fit the solution.
I had two tracks: with Firefox I didn't had the problem and the input field modification happens after few milliseconds the page reload.
So was a Chrome problem ? maybe. But disabling LastPass did the hat trick
I have been battling with this for years and the only solution that works for me is to override the FormGroup registerControl() function with the code below. It basically finds the input element and appends a guid to it.
@Component({ selector: '[fsForm]', template: `<ng-content></ng-content>`, changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FsFormComponent { public ngOnInit() { this._registerControl = this.ngForm.form.registerControl.bind(this.ngForm.form); this.ngForm.form.registerControl = (name: string, control: AbstractControl) => { const el: Element = this._element.nativeElement.querySelector(`input[name='${name}']`); if (el) { el.setAttribute('name', name + '_' + guid()); if (!el.getAttribute('autocomplete')) { el.setAttribute('autocomplete', 'none'); } } return this._registerControl(name, control); } }
} I need to do that for my all 89 inputs so, I insert that in my html file and work for me. Chrome 89.0
<script> $("input").each((a,b) => $(b).attr("autocomplete", "new-field-" + Math.random().toString(36).substring(2)))
</script> All other solutions seems not to work for me.
new-somename works in google. But only the last field that start with new is respected.
This directive can be used when multiple fields in a form shouldn't show autocomplete. see new-password in
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({ selector: 'input[autocompleteOff]' })
export class AutoCompleOffDirective { constructor(private el: ElementRef<HTMLInputElement>) {} @HostListener('focus') _ = () => (this.el.nativeElement.autocomplete = 'new-password'); @HostListener('blur') _1 = () => (this.el.nativeElement.autocomplete = '');
} setting name attribute fixed my problem in my angular material form. did that as explained out by Sanjay Verma, in his answer
<mat-form-field>
<mat-label>Track</mat-label>
<input name="track" matInput autocomplete="off" [(ngModel)]="track"> 1 I had encountered the same problem where autocomplete="false" was not working,then I tried autocomplete="off" but in some of my client system autocomplete="off" had worked. but failed for few user ,I suggest you to put in your input code :
<input autocomplete="nope">This conditions is working fine for me
this may be "clumsy" but it worked quite well for me.
component.html:
<input type="email" ngModel name="email" required #email="ngModel" [readonly]="isReadOnly">component.ts:
isReadOnly = true; ngOnInit() { //deal with pesky autocomplete setTimeout(() => { this.isReadOnly = false; }, 2000); }Am new so feedback is most appreciated.