Show / hide password input values with Vue.js 3 and the Composition API

Nowadays it's common to have the possibility to toggle the visibility of a password field on websites, applications, login screens etc. Implementing such a functionality with Vue.js 3 (and the Composition API) is really simple and straightforward.

Show / hide password input values with Vue.js 3 and the Composition API

Nowadays it's common to have the possibility to toggle the visibility of a password field on websites, applications, login screens etc. Implementing such a functionality with Vue.js 3 and the Composition API is straightforward (of course, this can also be achieved with pure JavaScript. But hey, JS frameworks are trendy and fancy, so why not implement it with one?)

First off we're going to implement the example with pure JavaScript, then we'll switch over to Vue.js 3 with the classic Options API and at the end we're gonna finish off with a Vue.js 3 example which makes use of the new Composition API, script setup and ref: sugar.

So first of all, what will our final result look like?

show/hide password in a Vue.js application

Implementation with pure JS

The basic idea behind showing / hiding the value of a password field is that you have a clickable element which switches the type attribute of the input field. That's basically all you have to do.

In order to understand how this works, let's first go through the states that the password input field can have:

  • type attribute set to password: this is the default state in which the input value is masqueraded
  • type attribute set to text: when the input field has this state, the input value is actually visible and not masqueraded anymore
<input type="password" id="password">
<button onclick="switchVisibility()">show / hide</button>

<script>
    const passwordField = document.querySelector('#password')

    function switchVisibility() {
      if (passwordField.getAttribute('type') === 'password') passwordField.setAttribute('type', 'text')
      else passwordField.setAttribute('type', 'password')
    }
</script>

What's going on here?

  • lines 1-2 declare our input field and the button, which calls the switchVisibility function when being clicked
  • line 5 gets our password input field into a variable so that we can edit the field's attributes later on
  • lines 7-10 is our implementation to handle the button click and toggle the type attribute value accordingly. We check if the attribute type of our password field is 'password'. If it is, we change the attribute to 'text', so that the actual input value will be visible. If however the type attribute is 'text', we change the type to 'password' to masquerade it's value again.

Implementation with Vue.js 3 (Options API)

If you are familiar with the basics of Vue.js 3 (Options API), this piece of code won't scare you at all. Anyways, we'll go through each line step by step. This code produces the exactly same visual output as the pure JS implementation above.

What's going on here?

  • lines 2-3 define the structure with our input and button elements
  • line 2 defines the input field, instructs Vue.js to keep the type attribute up to date with the value of the passwordFieldType property. Additionally, it keeps the instance's password property up to date with the input value and updates the input's value, if the property changes
  • line 3 defines our button and instructs Vue to call the method switchVisibility as soon as the button has been clicked
  • lines 8-13 define the data properties password and passwordFieldType and make them available to the template, methods, computed properties,...
  • lines 14-18 is again the same named function as in the pure JS example. Instead of manipulating the DOM directly, this time the method changes the value of the passwordFieldType property of our Vue instance. As soon as the passwordFieldType property gets updated, the type attribute of our password input field will automatically update.

Implementation with Vue.js 3 (Composition API)

Now that we've seen how we can implement the show/hide functionality in pure JS and Vue.js 3 with the Options API, let's bring this example one step further and implement it with Vue.js' new Composition API along with script setup and ref sugar.

The Composition API in Vue.js 3 is totally optional, as the Option API is still there, so don't worry if you've not heard about the Composition API yet. Feel free to first read about it and then come back to this example.

We ourselves already migrated most of our code to the new Composition API as it got a few advantages, mostly being related to scalability and code readability.

What's going on here?

  • lines 2-3 define the structure with our input and button elements
  • line 2 defines the input field, instructs Vue.js to keep the type attribute up to date with the value of the passwordFieldType variable. Additionally, it keeps the password variable up to date with the input value and updates the input's value, if the variable changes
  • line 3 defines our button and instructs Vue to call the method switchVisibility as soon as the button has been clicked
  • lines 7-8 define the variables password and passwordFieldType and make them available to the template, methods, computed properties,... Note that here we're making use of the new ref: sugar in order to keep the code concise and avoid the necessity to access refs with .value
  • line 10 is again the same named function as in the above example. As soon as we click the button, this function gets called and updates the passwordFieldType variable. As soon as the passwordFieldType variable gets updated, the type attribute of our password input field will automatically update.

Bonus - Vue.js Login Template

The above examples are still quiet small and concise. No CSS is involved at all. If you want to play around with a slightly more sophisticated example, I've prepared a live Codepen example and pushed a repository to GitHub which demonstrates the above mentioned techniques inside the context of a minimalistic login form.

If you have any further questions, aspects you are unsure with or found anything that is incorrect in this article, don't hesitate to reach out to me on Twitter: @ivansieder