When you logged in website, Chrome ask that do you want to save credentials for next visiting. If you accept that, Chrome saves your password then fill every password field(fields which types set as password) with your password on the web site.
This is expected behavior of this feature but sometimes comes annoying to users. For example in web site you have a field for API secret key and you decided to make that field type as password for security then Chrome thinks, this is login form and filling with your credential to form automatically. Today I will show how to prevent this behavior.
I made researches about how to prevent this behavior but answers or libraries I found for this behavior won't worked. So I decided to make my implementation and share with it.
Reason of That Behavior
As I mentioned before when form has password field and you saved your credentials to Chrome for that web site, Chrome things that, you are attempting to login this web site and fills every password field automatically.
Solution
Solution I found is very simple. I will implement with Vue on article but I think it could be easily implemented with React as well. My solution has 3 steps;
- Set
type='text'
and addautocomplete="off"
to all inputs in form for initial render. - When user focused password field, change field type as
password
- If user blur the input with empty value change input type as text.
Implementation in Vue
I will pass through application setup steps. I created to vue 2 app with default settings. Then added to simple login form on src/App.vue
file shown below.
<template>
<div id="app">
<div v-if="isloggedin" class="welcome">
Welcome {{username}}
</div>
<div v-else id="form-wrapper">
<label for="username">Username: </label>
<input
v-model="username"
class="form-input"
type="text"
name="username"
value=""
/>
<label for="password">Password: </label>
<input
v-model="password"
class="form-input"
type="password"
name="password"
value=""
/>
<button class="block" type="button" @click="saveCredentials">
Submit Form
</button>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
username: '',
password: '',
isloggedin: false
}
},
methods: {
saveCredentials() {
this.isloggedin = true;
}
}
}
</script>
<style>
#app {
display: flex;
flex: 1;
height: 100vh;
flex-direction: row;
justify-content: center;
align-items: center;
}
#form-wrapper {
flex-shrink: 1;
display:flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}
.form-input {
margin: 4px 0px;
}
.block {
width: 100%;
}
</style>
Assume that we visited and login this web site before and saved credentials to Chrome. On next visit to site the login form will looks like shown below.
To prevent this behavior, firstly we need to set input types as reactive and hold it in state. For initial render we need to set as text
to input type.
<input
v-model="password"
class="form-input"
:type="fieldTypes.password" // change this as reactive
name="password"
value=""
/>
data() {
return {
username: '',
password: '',
isloggedin: false,
fieldTypes: { // add this for change input type
password: 'text',
}
}
},
Then need to add @focus and @blur events to password input and trigger callback function for that events.
<input
v-model="password"
class="form-input"
:type="fieldTypes.password"
name="password"
value=""
@focus="handleType"
@blur="handleType"
/>
handleType(event) {
const { srcElement, type } = event;
const { name, value } = srcElement;
if(type === 'blur' && !value) {
this.fieldTypes[name] = 'text'
} else {
this.fieldTypes[name] = 'password'
}
}
Lastly to prevent chrome suggestions we need to add autocomplete="off"
to all inputs. You could add autocomplete="new-password"
to password field for strong password suggestions from browser. The final password field code looks like shown above.
<input
v-model="password"
class="form-input"
:type="fieldTypes.password"
name="password"
value=""
@focus="handleType"
@blur="handleType"
autocomplete="off"
/>
After all the final version of App.vue
looks like this.
<template>
<div id="app">
<div v-if="isloggedin" class="welcome">
Welcome {{username}}
</div>
<div v-else id="form-wrapper">
<label for="username">Username: </label>
<input
v-model="username"
class="form-input"
type="text"
name="username"
value=""
autocomplete="off"
/>
<label for="password">Password: </label>
<input
v-model="password"
class="form-input"
:type="fieldTypes.password"
name="password"
value=""
@focus="handleType"
@blur="handleType"
autocomplete="off"
/>
<button class="block" type="button" @click="saveCredentials">
Submit Form
</button>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
username: '',
password: '',
isloggedin: false,
fieldTypes: {
password: 'text',
}
}
},
methods: {
saveCredentials() {
this.isloggedin = true;
},
handleType(event) {
const { srcElement, type } = event;
const { name, value } = srcElement;
if(type === 'blur' && !value) {
this.fieldTypes[name] = 'text'
} else {
this.fieldTypes[name] = 'password'
}
}
}
}
</script>
<style>
#app {
display: flex;
flex: 1;
height: 100vh;
flex-direction: row;
justify-content: center;
align-items: center;
}
#form-wrapper {
flex-shrink: 1;
display:flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}
.form-input {
margin: 4px 0px;
}
.block {
width: 100%;
}
</style>
Top comments (1)
just give it a custom name. most browsers will show autocomplete if name is not specified or one of default ones "username" "password" etc. call it "myPassword" or whatever and autocompletion will be gone without specifying autocomplete='off'