---
title: "Creating a password validator component in Vue"
date: 2017-08-13
tags: post
---

Sometimes you procrastinate one feature by writing another. Even if that other feature is pretty small and inconsequential. [1](#fn:1)

For me, that _other_ feature — if you can even call it a feature — was password strength testing for [Buttondown](http://buttondown.email/).

This is one of those things that I always liked on other sites, but didn’t really know how to implement myself!

Turns out, the answer is “you let another library do all the heavy lifting”. That other library is [zxcvbn](https://github.com/dropbox/zxcvbn) by the fine folks at Dropbox: you can just pass in a string and it will return analysis on that string, including a `strength` (ranging from 0 to 4). Then all you have to do is write a little component like this:

```
<template>
  <span class="tiny">
      <pending-indicator :pending="pending" />
      <span v-if="!pending">
        <span class="error" v-if="strength === 0">Please choose a longer password.</span>
        <span class="error" v-if="strength === 1">Please choose a longer password.</span>
        <span class="warning" v-if="strength === 2">Better... but not quite enough.</span>
        <span class="info" v-if="strength === 3">This is a good password.</span>
        <span class="success" v-if="strength === 4">Great!  This is a secure password.</span>
      </span>
  </span>
</template>

<script>
  import _ from 'lodash';
  import zxcvbn from 'zxcvbn';

  export default {
    props: {
      password: String,
      onStrengthUpdate: Function,
    },

    data() {
      return {
        strength: null,
        checkedPassword: String,
      };
    },

    computed: {
      pending() {
        return !!this.password.length && this.checkedPassword !== this.password;
      },
    },

    watch: {
      password: _.debounce(async function () {
        this.strength = zxcvbn(this.password).score;
        this.checkedPassword = this.password;
      }, 500),
      strength(strength) { this.onStrengthUpdate(strength); },
    },
  };
</script>
```

A couple pieces of note:

*   `pending-indicator` is just a tiny component that returns a spinning icon when `pending` is true.
*   We debounce the watcher and cache the last-checked password in `checkedPassword` to avoid re-running the method every time the user types a single character.
*   `onStrengthUpdate` can be used by the parent component to conditionally disable registration.

And that’s it! It’s super simple. Here it is in action:

![](http://i.imgur.com/AFGf4m7.gif)

The finished product.

* * *

1.  Okay, _especially_ if that feature is pretty small and inconsequential. [\[return\]](#fnref:1)
