![Angular Super Forms Confirm Password](https://private-user-images.githubusercontent.com/2646053/259876646-4ecf90a2-6b30-4b5f-be92-b0c7544e64e3.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjYwMjMxNTgsIm5iZiI6MTcyNjAyMjg1OCwicGF0aCI6Ii8yNjQ2MDUzLzI1OTg3NjY0Ni00ZWNmOTBhMi02YjMwLTRiNWYtYmU5Mi1iMGM3NTQ0ZTY0ZTMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDkxMSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA5MTFUMDI0NzM4WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZmVmNTEzY2E2ZjhlZWM1OThlZjkzNWY1YjgyNDE0ZTFmNzJkNDA1MjAwZjU0NTljNzgzNGYzODE5MmI3NzRkOSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.F_5xSmYiA4O-SYPEcMnnJ3kRbM7clQ6mpL8Ulz79APc)
This is is a companion repo for Angular Super Forms: Confirm Password that demonstrates how to build a confirm password form with ng-bootstrap, error-tailor, component validation, styling, and form validation. Topics in this article include how to configure error-tailor for professional looking errors, validate individual fields, as well as creating a form that validates two components have the same value.
Clone this repo to your workspace:
git clone https://github.com/bobbyg603/ngx-confirm-password-example
Install the dependencies and start the application:
cd ngx-confirm-password-example && npm i && npm start
Enter invalid values into the form and click away from the inputs. Also enter a value for new password that doesn't match the value for confirm password before hitting submit. You should see several field validation errors as well as a form validation error at the bottom.
![Angular Super Forms Preview](https://private-user-images.githubusercontent.com/2646053/259898599-2f3095d1-5fa6-4103-b114-b4b6c4908f65.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjYwMjMxNTgsIm5iZiI6MTcyNjAyMjg1OCwicGF0aCI6Ii8yNjQ2MDUzLzI1OTg5ODU5OS0yZjMwOTVkMS01ZmE2LTQxMDMtYjExNC1iNGI2YzQ5MDhmNjUuZ2lmP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDkxMSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA5MTFUMDI0NzM4WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZGQ1NTYyMmE2MjdiNGVlODE2NGE0NjQwZGFkNDM0YzFlYjc0Y2ExNzFhYzFiZmZjZDYzMjY4YWFmYjI5ZTU5ZiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.4yuEFqds0ZnhjsPgJAuJZn0NxNHJHiHGt1qDAJpgdtw)
There are a few things in change-password-form.component.ts that are worth mentioning.
The first thing to notice is ControlsOf<ChangePasswordFormGroup>
. The ControlsOf
utility type allows us to convert an interfaceโs string types to FormControl<string>
types. This allows us to define the data model with a single interface and ensure that our form adheres to the same interface.
Hereโs what ControlsOf<ChangePasswordFormGroup>
evaluates to:
interface ControlsOf<ChangePasswordFormGroup> {
currentPassword: FormControl<string>;
newPassword: FormControl<string>;
confirmPassword: FormControl<string>;
}
More info on the ControlsOf
utility type can be found here.
The next piece worth noting is that weโre injecting NonNullableFormBuilder into the constructor. We use the NonNullableFormBuilder
because otherwise, we get compiler errors that FormControl<string | null>
cannot be assigned to an object expecting the type FormControl<string>
.
constructor(formBuilder: NonNullableFormBuilder) { ... }
Finally, weโve also created an array of validators that weโre passing to each of the form controls.
const validators = [Validators.required, Validators.minLength(8), Validators.pattern(upperLowerSymbolNumberRegex)];
const currentPassword = formBuilder.control('', validators);
const newPassword = formBuilder.control('', validators);
const confirmPassword = formBuilder.control('', validators);
Notice that weโre using Validators.pattern(upperLowerSymbolNumberRegex)
. This regular expression was found on Stack Overflow, and we created a const
with a descriptive name so that the next developer to work on the code can more easily understand the purpose of the complicated regular expression.
Last but not least, let's take a look at the template in change-password-form.component.html.
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-6 col-lg-3 text-center">
<div class="card">
<div class="card-body">
<h5 class="card-title">Change Password</h5>
<p class="card-text">Fill in the form below and click submit to update your password.</p>
<form class="form-group" [formGroup]="formGroup" (ngSubmit)="onSubmit()" errorTailor>
<input class="form-control" formControlName="currentPassword" placeholder="Current Password" type="password" >
<input class="form-control mt-2" formControlName="newPassword" placeholder="New Password" type="password">
<input class="form-control mt-2" formControlName="confirmPassword" placeholder="Confirm Password" type="password">
<button class="btn btn-primary mt-2" type="submit">Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
Notice that on the very end of the <form>
tag weโve added the errorTailor
directive. The errorTailor
directive makes validation messages magically appear when a form control has been changed and unfocused.
If you liked this example, please follow me on Medium and X, where I post programming tutorials and discuss tips and tricks that have helped make me a better programmer.
Thank you for your support โค๏ธ