Reputation: 2645
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" class="form-control input-lg ng-pristine ng-empty ng-invalid ng-invalid-required ng-touched" capitalize-full="" ng-model="user.ENDERECO" required="" placeholder="Digite seu endereço" autocomplete="off" name="street" style="opacity: 1; text-transform: uppercase;">
//markup sample
<form class="form form-horizontal" name="regForm"
autocomplete="false" novalidate role="form">
<input type="text" class="form-control input-lg"
name="cpf" ng-model="user.CPF" placeholder="Digite seu CPF"
required autocomplete="false" >
</form>
Upvotes: 38
Views: 119224
Reputation: 73
I tried several solutions, none worked for me, except this one:
Create an input text and style it to mask the characters, simple and it works.
<input type="text" pInputText [(ngModel)]="password" class="input-password-mask"/>
.input-password-mask {
-webkit-text-security: disc;
-moz-text-security: disc;
text-security: disc;
}
Upvotes: 0
Reputation: 3745
Here is an example, that turnsoff the autocomplete for email input field:
<input type="email" placeholder="email" autocomplete="off" />
We can also disable the autocomplete for an entire form, instead of a specific input field by setting an autocomplete="off" to the html element.
<form autocomplete="off" >
<input type="email" placeholder="email" />
<input type="password" placeholder="password" />
</form>
Upvotes: 1
Reputation: 465
The only thing that worked for me in Angular 12 was:
In the .component.ts file:
...
// resetForm() only works with FormGroupDirective, not FormGroup.
// We add it here.
@ViewChild('form') myFormNg: FormGroupDirective;
...
private createForm(): void {
this.myForm = new FormGroup({
'field1': new FormControl(null, [Validators.required]),
'field2': new FormControl(null, [Validators.required]),
'field3': new FormControl(null, [Validators.required]),
});
// This is a hack to get rid of the browser autofill.
// If the browser has autofilled the form in the next second after the form was created, reset the form.
// Otherwise, do nothing.
setTimeout(() => {
// field2 and field3 are the fields that gets autofilled.
// You can use any other field as long as it gets autofilled.
if (this.myForm.controls.field2.value !== '' || this.myForm.controls.field3.value !== '') {
this.clearForm();
}
// If we wait less that 1 second we risk the inputs not
// being reset because the autofill took more than 1 second.
}, 1000);
}
...
public clearForm(): void {
this.submitted = false;
this.errorMessage = '';
if (this.myFormNg) {
this.myFormNg.resetForm({
field1: '',
field2: '',
field3: ''
});
}
}
In the .html file:
...
<form [formGroup]="myForm" #form="ngForm">
...
Upvotes: 0
Reputation: 102
Usually what I do is I change type of input dynamically for example in angular :-
[type]="(field.length > 0)? 'password' : 'text'"
In this manner, the browser is unable to recognize the password field the first time you click it and will not provide a suggestion; however, if the field value has been input once and then erased, the browser will provide a suggestion. (Atleast it is not providing suggestion for the first time)
Upvotes: 0
Reputation: 9034
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 https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
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);
}
Upvotes: 5
Reputation: 1
setting name attribute fixed my problem in my angular material form. did that as explained out by Sanjay Verma, in his answer https://stackoverflow.com/a/66739412/6092524
<mat-form-field>
<mat-label>Track</mat-label>
<input name="track" matInput autocomplete="off" [(ngModel)]="track">
Upvotes: -1
Reputation: 97
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" class="form-control" />
<input type="password" autocomplete="new-password" formControlName="password" class="form-control" />
E.g, 2:
<input type="email" autocomplete="cc-name" formControlName="email" class="form-control" />
<input type="password" autocomplete="cc-name" formControlName="password" class="form-control" />
Upvotes: 5
Reputation: 7334
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 https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
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 = '');
}
Upvotes: 0
Reputation: 409
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.
Upvotes: 22
Reputation: 19
autocomplete="off"
not working you just need to put something like this.
<input class="form-control" autocomplete="new-username"
formControlName="username" name="username" type="text">
instead of:
<input class="form-control" autocomplete="off"
formControlName="username" name="username" type="text">
Upvotes: 1
Reputation: 121
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 class="form-control" type="text" name="first_name" autocomplete="new-name" required>
Upvotes: 1
Reputation: 1357
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.
Upvotes: 2
Reputation: 1
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>
Upvotes: -1
Reputation: 1626
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 🙏
Upvotes: 2
Reputation: 22
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
Upvotes: -2
Reputation: 1160
On Chrome, specifying autocomplete="off"
didn't work for me. However, autocomplete="disabled"
worked properly.
You can test and evaluate using this page: https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_autocomplete (try changing the off to disabled using your browser).
Goodluck!
Upvotes: 10
Reputation: 41
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);
}
}
}
Upvotes: -1
Reputation: 379
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.
Upvotes: -3
Reputation: 2507
Simply put autocomplete="new-feildName" on html control
Example :
<input class="signup-input-field-01" autocomplete="new-phone"
formControlName="phone" name="phone" type="text">
Upvotes: 19
Reputation: 510
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)
}
}
Upvotes: 2
Reputation: 109
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');
});
}
}
}
}
Upvotes: 7
Reputation: 19
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
Upvotes: -1
Reputation: 2091
The autocomplete="off" is effectively respected by Chrome, but what you're experiencing is the Chrome autofill functionality that takes over, ignoring autocomplete="off": https://developers.google.com/web/updates/2015/06/checkout-faster-with-autofill.
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: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill
Upvotes: 12
Reputation: 323
I would assume the option is only needed on the input tag.
<input name="q" type="text" autocomplete="off"/>
Upvotes: 2