DEV Community

Uzochukwu Eddie Odozi
Uzochukwu Eddie Odozi

Posted on • Edited on

Build a Password Strength Checker With Angular

In this post, we are going to create a simple form with password input field. We will then add a password strength checker functionality. We are going to add the following rules to the password input form. Password

  • Must be at least 6 characters long
  • Must contain at least one uppercase letter
  • Must contain at least one lowercase letter
  • Must contain at least one number
  • Must contain at least one special character

We are going to validate each of the rules above using RegExp and then display some color bars to indicate how strong the password is. At the end of the post, we are going to see how to use

  • Reactive Forms (In a simple way)
  • Component interactions using @Input and @Output decorators
  • Colors and bars to represent password strength

Here is how the final app will look like:

Getting Started

First, we are going to create a new project using the Angular CLI by running the command



ng new password-strength


Enter fullscreen mode Exit fullscreen mode

In this application, there is no navigation so there is no need to add a routing file.

For simplicity sake, let us install bootstrap 4.



npm install bootstrap


Enter fullscreen mode Exit fullscreen mode

Add this



@import '~bootstrap/dist/css/bootstrap.min.css';


Enter fullscreen mode Exit fullscreen mode

to your styles.scss or styles.css file in the src directory of your project. Note that you can use any other library of your choice for styling the app.

If you are using yarn



yarn add bootstrap


Enter fullscreen mode Exit fullscreen mode

Creating the Form

In the app.module.ts, add the import of ReactiveFormsModule



import { ReactiveFormsModule } from '@angular/forms';


Enter fullscreen mode Exit fullscreen mode

Then add the ReactiveFormsModule into the imports array



imports: [
    BrowserModule,
    ReactiveFormsModule
]


Enter fullscreen mode Exit fullscreen mode

You can use a Template Driven Form if you so choose. Here I decided to go with with Reactive Forms.

Now, in the app.component.html file, add the html template



<div class="container">
  <div class="row">
      <div class="col mt-5 col-xs-6 col-md-6 col-lg-6">
        <h2>Check Password Strength</h2>
        <br>
      <form>
        <div class="form-group">
          <input type="password" class="form-control" autocomplete="off" placeholder="Password">
        </div>
        <button type="submit" class="btn btn-primary">
          Submit
        </button>
      </form>
    </div>
  </div>
</div>


Enter fullscreen mode Exit fullscreen mode

The form contains a password input field. The classes added to the div elements are from bootstrap 4.

In the app.component.scss or app.component.css depending on what you selected, add to the file



.col {
  margin: 0 auto;
  text-align: center;
}


Enter fullscreen mode Exit fullscreen mode

To use a Reactive Form in Angular, we need to add a formGroup property to the form and then add a formControlName to the input field.

On the form, add



[formGroup]="passwordForm"


Enter fullscreen mode Exit fullscreen mode

So the form looks something like



<form [formGroup]="passwordForm">
    ...
</form>


Enter fullscreen mode Exit fullscreen mode

Also, on the password input field, add



formControlName="password"


Enter fullscreen mode Exit fullscreen mode

Next, we need to initialize the Reactive form. In the app.component.ts file, add the imports



import { FormGroup, FormBuilder, Validators } from '@angular/forms';


Enter fullscreen mode Exit fullscreen mode

The FormGroup tracks the state of the form-control elements. The FormBuilder helps to reduce the boilerplate required to create the form. Validators provides some set of built-in validators to be used. We are using the classes so we can initialize the form.

Create a property of type FormGroup.



passwordForm: FormGroup;


Enter fullscreen mode Exit fullscreen mode

We need the construtor and ngOnInit methods. First, we need to implement the OnInit interface and then import from @angular/core. The export class line will become



export class AppComponent implements OnInit


Enter fullscreen mode Exit fullscreen mode

Add both methods



constructor(private fb: FormBuilder) {}

ngOnInit() {
    this.passwordForm = this.fb.group({
        password: ['', Validators.required],
    });
}


Enter fullscreen mode Exit fullscreen mode

In the constructor, the FormBuilder class is injected so that we can use methods available in the class. In the ngOnInit method, the passwordForm is initialized using the FormBuilder and then validating the password field. The key in the object inside the group method must match the formControlName in the template. The required validator is added to the input field. Now we have the form and the password field setup. We can now create a new component that will be used to display the password strength.

Password Strength Component

The password strength component which will be added as a child of the main component will be used to display some bars that will indicate the strength of the password the user types. As the user types into the password field, the bars will automatically be updated with different colors.

To create a new component, we run



ng generate component password-strength


Enter fullscreen mode Exit fullscreen mode

This component will be automatically added to the app.module.ts file. In the password-strength.component.html file, add



<div class="strength">
  <ul class="strengthBar">
    <li class="point" [style.background-color]="bar0"></li>
    <li class="point" [style.background-color]="bar1"></li>
    <li class="point" [style.background-color]="bar2"></li>
    <li class="point" [style.background-color]="bar3"></li>
  </ul>
  <br>
</div>


Enter fullscreen mode Exit fullscreen mode

Add these properties to the password-strength.component.ts file



bar0: string;
bar1: string;
bar2: string;
bar3: string;


Enter fullscreen mode Exit fullscreen mode

In the styles file of the component, add



.strengthBar {
  display: inline;
  list-style: none;
  margin: 0;
  padding: 0;
  vertical-align: 2px;
}

.point:last-of-type {
  margin: 0 !important;
}

.point {
  background: #DDD;
  border-radius: 2px;
  display: inline-block;
  height: 5px;
  margin-right: 1px;
  width: 62px;
}

p {
  font-weight: bold;
  font-size: 20px;
}


Enter fullscreen mode Exit fullscreen mode

Go to the app.component.html file and add the password-strength component as a child component by using the component selector name <app-password-strength></app-password-strength>. The component should be added after the password input field.



<div class="container">
  <div class="row">
      <div class="col mt-5 col-xs-6 col-md-6 col-lg-6">
        <h2>Check Password Strength</h2>
        <br>
      <form [formGroup]="passwordForm">
        <div class="form-group">
          <input type="password" class="form-control" formControlName="password" autocomplete="off" placeholder="Password">
          <app-password-strength></app-password-strength>
        </div>
        <button type="submit" class="btn btn-primary">
          Submit
        </button>
      </form>
    </div>
  </div>
</div>


Enter fullscreen mode Exit fullscreen mode

The component consists of a div with ul and li tags. The li tags represent the bars on the page. As a user types into the input field, the color that will be specified in the component's class will be displayed. Once the password matches all specified characters, the color of all bars will become green.

Password Strength Functionality

The interaction between the parent and child component will be achieved using the @Input decorator. The password from the password form will be bound to an Input property coming from the password strength component. There are different ways whereby the data can be intercepted. We are going to intercept the data using the ngOnChanges method.

Let us create an input property called passwordToCheck



@Input() public passwordToCheck: string;


Enter fullscreen mode Exit fullscreen mode

Then create an array of colors to be displayed on the bars. The number of colors in the array should match the number of bars in the component.



private colors = ['darkred', 'orangered', 'orange', 'yellowgreen'];


Enter fullscreen mode Exit fullscreen mode

Now, let us create a method to check the strength of the password. Add the following code



checkStrength(p) {
  // 1
  let force = 0;

  // 2
  const regex = /[$-/:-?{-~!"^_@`\[\]]/g;
  const lowerLetters = /[a-z]+/.test(p);
  const upperLetters = /[A-Z]+/.test(p);
  const numbers = /[0-9]+/.test(p);
  const symbols = regex.test(p);

  // 3
  const flags = [lowerLetters, upperLetters, numbers, symbols];

  // 4
  let passedMatches = 0;
  for (const flag of flags) {
    passedMatches += flag === true ? 1 : 0;
  }

  // 5
  force += 2 * p.length + ((p.length >= 10) ? 1 : 0);
  force += passedMatches * 10;

  // 6
  force = (p.length <= 6) ? Math.min(force, 10) : force;

  // 7
  force = (passedMatches === 1) ? Math.min(force, 10) : force;
  force = (passedMatches === 2) ? Math.min(force, 20) : force;
  force = (passedMatches === 3) ? Math.min(force, 30) : force;
  force = (passedMatches === 4) ? Math.min(force, 40) : force;

  return force;
}
```
First, a property called force of type number is defined which is used as the return type of the method. The value assigned to the property will be used to determine the strength of the password. The 2nd part is where the regular expressions are defined. The regex of special characters, lowercase test, uppercase test, number test and regex test. The 3rd part is an array that contains the regular expressions to be used. In the 4th part, a property called `passedMatches` of type number is defined and its value is incremented inside the loop depending on the regular expression that is satisfied. So, if the first criteria in the flags array is met, the value of `passedMatches` is incremented by 1. If the second criteria is met, the current value is also incremented by 1 until all criterias are met. Otherwise, the value 0 is added. The 5th part checks if the password length is greater than 10 and then multiplies the `passedMatches` value by 10. The 6th part is where the length of the password (which needs to be at least 6 characters) is checked. The 7th part is where the final `force` value is set based on the value of `passedMatches`. Then the force value is returned.

Next we need to bind the `passwordToCheck` input property to the form password. Add `[passwordToCheck]="signupForm.value.password"` to the child component inside `app.component.html`.
```html
<app-password-strength [passwordToCheck]="signupForm.value.password"></app-password-strength>
```
The `passwordToCheck` is the `@Input` property defined in the password strength component. It is bound to the password value from the `formGroup`. So whatever value is stored in the password value field, it will be received in the child component.

Like i said earlier, there are multiple ways the password value can be intercepted in the child component. You can checkout out this [documentation](https://angular.io/guide/component-interaction#pass-data-from-parent-to-child-with-input-binding). We are going to be using the ngOnChanges method to intercept the changes. 

Implement the `OnChanges` interface in the `PasswordStrengthComponent` class and then import the interface from `@angular/core`. Next is to add the method
```js
ngOnChanges(changes: { [propName: string]: SimpleChange }): void {
  const password = changes.passwordToCheck.currentValue;
  this.setBarColors(4, '#DDD');
  if (password) {
    const c = this.getColor(this.checkStrength(password));
    this.setBarColors(c.index, c.color);
  }
}

private getColor(s) {
  let index = 0;
  if (s === 10) {
    index = 0;
  } else if (s === 20) {
    index = 1;
  } else if (s === 30) {
    index = 2;
  } else if (s === 40) {
    index = 3;
  } else {
    index = 4;
  }
  return {
    index: index + 1,
    color: this.colors[index]
  };
}

private setBarColors(count, col) {
  for (let n = 0; n < count; n++) {
    this['bar' + n] = col;
  }
}
```

The `ngOnChanges` method takes in property of type `SimpleChange`. In the SimpleChange property, we have the `passwordToCheck` input property which contains the password's currentValue. As the value changes, the password is intercepted by the ngOnChanges method. The `setBarColors` defined before the if statement is used to set a default color for the bars. If the password is available then the `getColor` method is called and it takes in the `checkStrength` which in turn takes the password as a parameter. Note that the `checkStrength` returns a number which is used in the `getColor`. The `setBarColors` is used to set the colors in the colors array on the bars.

In the `getColor` method, if the return value of the `checkStrength` is equal 10 then we set the index value to zero and so on. Then an object with the index and color is returned. Recall that the bars have a style property with a number appended to the name. E.g: `bar0, bar1, bar2, bar3`. The `setBarColors` is just used to set the colors from the array on the bars.

![](https://thepracticaldev.s3.amazonaws.com/i/27lvks38xkhyuyjft9xi.gif)

We can add more functionalities by displaying a message as the user types and also disabling the submit button unless the password is valid.

### Disable Button
To disable the submit button, we are going to use the `@Output` decorator to send data from child to parent. In this case from the password strength component to the main component.

Add this line to the password strength component class:
```js
@Output() passwordStrength = new EventEmitter<boolean>();
```

Add the `Output` interface and `EventEmiiter` to the `@angular/core` imports. The EventEmitter will emit a boolean value. In this case a true value when the password becomes valid and the emitted value will be used to enable the submit button.

In the `ngOnChanges` method, add the below line into the if statement
```js
const pwdStrength = this.checkStrength(password);
pwdStrength === 40 ? this.passwordStrength.emit(true) : this.passwordStrength.emit(false);
```
Here we are setting the return value of `checkStrength` method to a variable. Then using a ternary operator to emit a boolean value. If pwdStrength is equal to 40 then emit `true`. If the pwdStrength is less than 40 then emit `false`. The line is the same as
```js
if (pwdStrength === 40) {
  this.passwordStrength.emit(true)
} else {
  this.passwordStrength.emit(false)
}
```

The next step is to use this `@Output` eventemitter in the main component. In the component `<app-password-strength></app-password-strength>`, add
```js
(passwordStrength)="passwordValid($event)"
```
which then becomes
```html
<app-password-strength [passwordToCheck]="signupForm.value.password" (passwordStrength)="passwordValid($event)"></app-password-strength>
```

The `passwordStrength` is the output property while `passwordValid($event)` is a method that needs to be defined in the main class component. The `$event` property added as a parameter will contain the emitted boolean value.

Add a new property to the main component's class.
```js
passwordIsValid = false;
```
And also add the `passwordValid` method
```js
passwordValid(event) {
  this.passwordIsValid = event;
}
```
The emitted value from the EventEmitter is set to the `passwordIsValid` property. We can now use this property to disable the button.

On the submit button, add `[disabled]="!passwordIsValid"`.
```html
<button type="submit" class="btn btn-primary" [disabled]="!passwordIsValid">
  Submit
</button>
```
So if the value of `passwordIsValid` is false then the button will be disabled. When the password is valid, the button will be enabled on the page.

![](https://thepracticaldev.s3.amazonaws.com/i/hz2lzr3gqq5w8segtgzx.gif)

The last part to take care of is to add a message as the user types. Create two new variables
```js
msg: string;
msgColor: string;
```
in the password strength component class. Then add a `p` tag after the `ul` tag in the template with the `msg` varaible.
```html
<p [style.color]="msgColor">{{msg}}</p>
```
Inside the if statement in the `ngOnChanges` method, add this switch statement
```js
switch (pwdStrength) {
  case 10:
    this.msg = 'Poor';
    break;
  case 20:
    this.msg = 'Not Good';
    break;
  case 30:
    this.msg = 'Average';
    break;
  case 40:
    this.msg = 'Good';
    break;
}
```
If the `pwdStrength` is 10 then the msg is set equal to `Poor` and so on. So as the user types into the input field, the msg variable is updated. Also, we want to be able to clear the message if the user decides to clear the input field. So add an else part to the if statement and add
```js
this.msg = '';
```
If the input field is empty then the msg should be cleared. In the `getColor` method, add `this.msgColor = this.colors[index]` before the return statement. The method now becomes
```js
private getColor(s) {
  ...
  this.msgColor = this.colors[index];
  ...
}
```

![](https://thepracticaldev.s3.amazonaws.com/i/p9o10dc3bsm8utc32ejw.gif)

# Conclusion
So far we have been able to add the password strength functionality. We saw how to use Reactive Forms in Angular, @Input and @Output decorators for component interactions. You can add more regular expression validations to the password.

[Find the github repo for the sample app here](https://github.com/uzochukwueddie/password-strength).

If you are interested in more Angular related stuff, you can follow me [Twitter](https://twitter.com/uzochukwueddie) and also subscribe to my [YouTube channel](https://www.youtube.com/channel/UCqTEGhqVPcjfhs7_bQjnoRA/videos?view_as=subscriber).
Enter fullscreen mode Exit fullscreen mode

Top comments (0)