{"id":25591377,"url":"https://github.com/bobbyg603/ngx-confirm-password-example","last_synced_at":"2026-05-15T08:02:18.002Z","repository":{"id":187073569,"uuid":"676220013","full_name":"bobbyg603/ngx-confirm-password-example","owner":"bobbyg603","description":"📐🦸📋 Angular custom validator example that ensures the values of two form controls are equal","archived":false,"fork":false,"pushed_at":"2023-08-11T00:07:57.000Z","size":156,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-15T09:12:30.299Z","etag":null,"topics":["angular","error-tailor","forms","ng-neat","reactive-forms"],"latest_commit_sha":null,"homepage":"https://medium.com/p/bd95906f220f","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bobbyg603.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-08T17:44:08.000Z","updated_at":"2024-04-15T09:12:30.300Z","dependencies_parsed_at":"2023-08-08T22:23:26.228Z","dependency_job_id":null,"html_url":"https://github.com/bobbyg603/ngx-confirm-password-example","commit_stats":null,"previous_names":["bobbyg603/ngx-confirm-password-example"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobbyg603%2Fngx-confirm-password-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobbyg603%2Fngx-confirm-password-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobbyg603%2Fngx-confirm-password-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobbyg603%2Fngx-confirm-password-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bobbyg603","download_url":"https://codeload.github.com/bobbyg603/ngx-confirm-password-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239993959,"owners_count":19730779,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","error-tailor","forms","ng-neat","reactive-forms"],"created_at":"2025-02-21T09:51:13.856Z","updated_at":"2025-11-11T08:05:40.763Z","avatar_url":"https://github.com/bobbyg603.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## 📐📋🦸 Angular Super Forms: Confirm Password\n\n\u003cimg alt=\"Angular Super Forms Confirm Password\" src=\"https://github.com/bobbyg603/ngx-confirm-password-example/assets/2646053/4ecf90a2-6b30-4b5f-be92-b0c7544e64e3\" width=\"540px\" height=\"auto\"\u003e\n\n[![medium profile link](https://img.shields.io/badge/Medium-12100E?style=for-the-badge\u0026logo=medium\u0026logoColor=white)](https://medium.com/p/bd95906f220f)\n[![twitter profile link](https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge\u0026logo=twitter\u0026logoColor=white)](https://twitter.com/bobbyg603/status/1689632582994907136)\n[![StackBlitz](https://img.shields.io/badge/StackBlitz-Edit-blue?style=for-the-badge\u0026logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAABECAYAAAD+1gcLAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH5AINBw4X0bTGRQAABSxJREFUaN7VmVtsFFUYx//fmQW79bbd2QKpaIIaDcGoifFBEgMGqTTRRA01SgxE5Rbi7QG6S3lgo9J2twpeotxEQlCigLdoQwJ4ARN9QB9MRCNRDBdRzE7LJbTSmTl/H4BYStmd2Z3tDOdt5lzml/9833fO9x0gYi2xgom6Tt5aapyKEnRDlrVGPzfGT+G3SwZ87HLGT8f5uYD7jmSl99IAX80RfTY3A5wMqDVepoQPnqVKHtMbAN4PyJeFtPwafXBSknG9UoDHAIDQq7xODRU8mdc5Aeaeffy7O2F8GnnwZM5dKsCic88CrMU8sSMNbubdZwTIDnjlOoZa52eNYQc3c84sEK+d/1a6ji2UA5EFN3POw4C8fcYy/m+a3p1y2MGTOXsqIJsAxAZ1Hei53tgeSfBkBycK1McALrswJGIVHhE3cuD1ed4uorsAXD5Ed7/hqvXlrFtV8LpO3qKpdwJIDLn/AB/+s0SORgp8VJ43KK23AzAvNsagWlXu+lKV6LGc14itvyEwrsiwX6wWNQEijITiY9pYD1vvKAENAG+VC40hQlNlNt3Bq22lt4EYX2Jor6PVe5V8KzDFG7KsFXE/A3GHB/vcdHyx9IQPnuXI/ji3CuRuT+N1+U4ZHPhmGqk43yXY5C0ccE9hsfwQLjgp5n69hmCz9ylYGcRPrgg8ldfLIXjSx5RjNX3GB6GCm3m3ncDz/v4QNnjJ4KsGbubdVhAZ35YFtTaoKOY7jps5dwGIZf73aH7dnZa9QYH72vLNDmcmRNaX86eEnGvT2BoIdA0o3pV2HgRkS9C7bXnRDGlPypmd9r2AvB8FaAFetDJGvqTiyU7eJWeOp1cgfOo3rRbj6ZJRJdHB20TrrkhAAxutXvVsSedMtfEmGno3gNHhM8snVp80IytO0The18HraOgdkYCm7KyLy6MDoYdUfNQyjnZjeheAm8NXmt/FlDH16CI5dUHaN/DhypeZUqK/AkomAsMQ8fCjq41GKy0nim75ydd51UjX3QZgQgQccV/MUfcVSzYM4Mw1hnPa7QJkYgSgD2qqe6xWOVL8kLWaI3ptbgFkUgSgjwpUY09GDpY8ZJnH9UsExhPYH8CuVgtgTJlzC5pqipXxdpUSaF3FzLkdANJleOIJETWlkJbvh78glOVIM64PARjlc2afiGoqtMiuUMoTqRp3ehnQtpDNfqEDBdeC+T6nuELOLGRiXVVPJC5u2xwP6L0+1qOQ8wqZWNmpXECK6wV+RBCipRLoQBRvyLL2dFwfBlDnTWos7W4xXgi3IATg31p3hldoEG8EAR0IuEC8OuUGK62eCyoYVARutvNOL9VZQD6yxqmnKqmHB6u46PkejHp7XVxmlHOzVhXnTKxgwujXhzH0bdo56m9jymgcKhEITXFl61lFoYV7BMa0akCjkjqJEHOKdP/U7xhNJ1vlZLXOv2Upnmq3JxfJlH4XRzWebBWrmgf38hRXav5F4vSfjqGmHl8if1W/NuSzjWljvW3oQxh0Ly9AQRtqUvdC+Xk4UiXfpmLH9JzB0CBOQKtpwwXtHzxLJcTsQW97FdQDQVxIVc3GUzVuEyEDb4z7NTndysju4c6qfSlOOc8pXQof78nEtoVRDvDsnMlXeK04+o+ztRgSnNOdjq1DSM2z4uLoeecKSCQWhgntXfEsY2ZcHwDQAMESq8VoC7ty5EnxZK37EIAGAV6NArT3c3def2Hm3HdASlSYSipe384bAR6x+tTsIBOBqoMTzlirVz2BrOgoWcF/mizikfkwKiQAAAAASUVORK5CYII=)](https://stackblitz.com/edit/github-ktbxdp-ftgv1g)\n\nThis is is a companion repo for [Angular Super Forms: Confirm Password](https://medium.com/p/bd95906f220f) that demonstrates how to build a confirm password form with [ng-bootstrap](https://ng-bootstrap.github.io/#/home), [error-tailor](https://github.com/ngneat/error-tailor), c[omponent validation](https://medium.com/p/bd95906f220f#c02e), [styling](https://medium.com/p/bd95906f220f#b7b4), and [form validation](https://medium.com/p/bd95906f220f#e1f3). 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.\n\n## ☕️ TL;DR\n\nClone this repo to your workspace:\n\n```sh\ngit clone https://github.com/bobbyg603/ngx-confirm-password-example\n```\n\nInstall the dependencies and start the application:\n\n```sh\ncd ngx-confirm-password-example \u0026\u0026 npm i \u0026\u0026 npm start\n```\n\nEnter 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.\n\n\u003cimg alt=\"Angular Super Forms Preview\" width=\"540px\" src=\"https://github.com/bobbyg603/ngx-confirm-password-example/assets/2646053/2f3095d1-5fa6-4103-b114-b4b6c4908f65\"\u003e\n\n## 🕵️ Inspecting the Code\n\nThere are a few things in [change-password-form.component.ts](https://github.com/bobbyg603/ngx-confirm-password-example/blob/main/src/app/change-password-form/change-password-form.component.ts) that are worth mentioning.\n\nThe first thing to notice is [`ControlsOf\u003cChangePasswordFormGroup\u003e`](https://github.com/bobbyg603/ngx-confirm-password-example/blob/4fe68dd3255808e13742b573437987fb25c9b697/src/app/change-password-form/change-password-form.component.ts#L14C26-L14C26). The `ControlsOf` utility type allows us to convert an interface’s string types to `FormControl\u003cstring\u003e` types. This allows us to define the data model with a single interface and ensure that our form adheres to the same interface.\n\nHere’s what `ControlsOf\u003cChangePasswordFormGroup\u003e` evaluates to:\n\n```ts\ninterface ControlsOf\u003cChangePasswordFormGroup\u003e {\n  currentPassword: FormControl\u003cstring\u003e;\n  newPassword: FormControl\u003cstring\u003e;\n  confirmPassword: FormControl\u003cstring\u003e;\n}\n```\n\nMore info on the `ControlsOf` utility type can be found [here](https://betterprogramming.pub/how-to-build-a-strongly-typed-angular-14-super-form-86837965a0e5).\n\nThe next piece worth noting is that we’re injecting NonNullableFormBuilder into the constructor. We use the [`NonNullableFormBuilder`](https://angular.io/guide/typed-forms#formbuilder-and-nonnullableformbuilder) because otherwise, we get compiler errors that `FormControl\u003cstring | null\u003e` cannot be assigned to an object expecting the type `FormControl\u003cstring\u003e`.\n\n```ts\nconstructor(formBuilder: NonNullableFormBuilder) { ... }\n```\n\nFinally, we’ve also created an array of validators that we’re passing to each of the form controls.\n\n```ts\nconst validators = [Validators.required, Validators.minLength(8), Validators.pattern(upperLowerSymbolNumberRegex)];\n\nconst currentPassword = formBuilder.control('', validators);\nconst newPassword = formBuilder.control('', validators);\nconst confirmPassword = formBuilder.control('', validators);\n```\n\nNotice that we’re using `Validators.pattern(upperLowerSymbolNumberRegex)`. This regular expression was found on [Stack Overflow](https://stackoverflow.com/a/1559788/2993077), 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.\n\nLast but not least, let's take a look at the template in [change-password-form.component.html](https://github.com/bobbyg603/ngx-confirm-password-example/blob/main/src/app/change-password-form/change-password-form.component.html).\n\n```html\n\u003cdiv class=\"container\"\u003e\n  \u003cdiv class=\"row justify-content-center\"\u003e\n    \u003cdiv class=\"col-12 col-md-6 col-lg-3 text-center\"\u003e\n      \u003cdiv class=\"card\"\u003e\n        \u003cdiv class=\"card-body\"\u003e\n          \u003ch5 class=\"card-title\"\u003eChange Password\u003c/h5\u003e\n          \u003cp class=\"card-text\"\u003eFill in the form below and click submit to update your password.\u003c/p\u003e\n          \u003cform class=\"form-group\" [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\" errorTailor\u003e\n            \u003cinput class=\"form-control\" formControlName=\"currentPassword\" placeholder=\"Current Password\" type=\"password\" \u003e\n            \u003cinput class=\"form-control mt-2\" formControlName=\"newPassword\" placeholder=\"New Password\" type=\"password\"\u003e\n            \u003cinput class=\"form-control mt-2\" formControlName=\"confirmPassword\" placeholder=\"Confirm Password\" type=\"password\"\u003e\n            \u003cbutton class=\"btn btn-primary mt-2\" type=\"submit\"\u003eSubmit\u003c/button\u003e\n          \u003c/form\u003e\n        \u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n```\n\nNotice that on the very end of the `\u003cform\u003e` tag we’ve added the `errorTailor` directive. The `errorTailor` directive makes validation messages magically appear when a form control has been changed and unfocused.\n\n## 🧑‍💻 Next Steps\n\nIf you liked this example, please follow me on [Medium](https://bobbyg603.medium.com/) and [X](https://twitter.com/bobbyg603), where I post programming tutorials and discuss tips and tricks that have helped make me a better programmer.\n\n**Thank you for your support ❤️**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbobbyg603%2Fngx-confirm-password-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbobbyg603%2Fngx-confirm-password-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbobbyg603%2Fngx-confirm-password-example/lists"}