ngx-password-strength-validator
v1.0.2
Published
Standalone Angular password strength indicator + reactive-forms validator. Strict types, signal API, CSS-variable theming, i18n. Zero CSS framework dependencies.
Maintainers
Keywords
Readme
ngx-password-strength
A standalone Angular presentation primitive for password strength feedback, plus a matching reactive-forms ValidatorFn. Strict types, fully configurable, theme-able via CSS variables, zero CSS framework dependencies.
Bring your own input. <ngx-password-strength> never renders an <input>. You give it a [password] value from wherever — a signal, ngModel, formControlName, server preview — and it draws the bar + requirements list.
📖 Full walkthrough: USER_GUIDE.md
Install
npm install ngx-password-strength-validatorPeer deps: @angular/common, @angular/core (and @angular/forms if you use passwordValidator), all >= 17.0.0.
Implementation
Standalone component — add it to imports and bind [password]. Declare your config as a typed variable in TS (not inline in the template) so your IDE autocompletes every field of PasswordValidatorConfig.
app.component.ts — typed config + handlers (full IDE autocomplete):
import { Component, signal } from '@angular/core';
import {
PasswordStrengthComponent,
type PasswordValidatorConfig,
type PasswordStrengthState,
} from 'ngx-password-strength-validator';
@Component({
selector: 'app-root',
standalone: true,
imports: [PasswordStrengthComponent],
templateUrl: './app.component.html',
})
export class AppComponent {
readonly value = signal('');
readonly canSubmit = signal(false);
// 👇 Autocomplete shows every config field as you type
readonly pwdConfig: PasswordValidatorConfig = {
minLength: 12,
maxLength: 32,
requireUppercase: true,
requireLowercase: true,
requireDigit: true,
requireSpecial: true,
};
onStrength(state: PasswordStrengthState) {
// state.index: 0 | 1 | 2 | 3 ; state.label: 'Weak' | 'Fair' | 'Good' | 'Strong'
}
}app.component.html — bind the variables, never inline-literal:
<input type="password" #pwd (input)="value.set(pwd.value)" />
<ngx-password-strength
[password]="value()"
[config]="pwdConfig"
(strengthChange)="onStrength($event)"
(validChange)="canSubmit.set($event)"
/>Why a typed variable instead of
[config]="{ minLength: 12 }"? Angular Language Service has weak autocomplete inside object literals in template bindings — typing[config]="{ |"rarely surfaces the inner keys. In a.tsfile with an explicitPasswordValidatorConfigannotation, autocomplete works perfectly. Bonus: you can pass the samepwdConfigreference topasswordValidator(pwdConfig)for UI/validator parity.
The component is also happy without any input box — pass any string (e.g. a server-side preview):
<ngx-password-strength [password]="someStringFromAnywhere" [config]="pwdConfig" />Parameters (Inputs)
| Input | Type | Default | Description |
|---|---|---|---|
| password | string | '' | The value to evaluate. Bring your own — signal, ngModel, formControlName, anything. |
| config | PasswordValidatorConfig | {} | Rule configuration. See table below. |
| labels | PasswordStrengthLabels | {} | i18n overrides for rule labels and strength bucket names. Unset keys fall back to English defaults. |
| requirementsAriaLabel | string | 'Password requirements' | aria-label for the requirements list. |
PasswordValidatorConfig
| Field | Type | Default | Purpose | Failure key |
|---|---|---|---|---|
| minLength | number | 12 | Minimum length. | length |
| maxLength | number \| undefined | unlimited | Maximum length. Omit for no upper bound. | length |
| requireUppercase | boolean | true | Require an uppercase Unicode letter (\p{Lu}). | upper |
| requireLowercase | boolean | true | Require a lowercase Unicode letter (\p{Ll}). | lower |
| requireDigit | boolean | true | Require a digit (0–9). | digit |
| requireSpecial | boolean | true | Require a non-letter, non-digit, non-whitespace character. | special |
| email | string | — | If set, password must not contain this email or its local part (case-insensitive). | noEmail |
| username | string | — | If set, password must not contain this username (case-insensitive). | noUsername |
Two rules are always active and cannot be disabled: length (above) and noSpace (no whitespace anywhere in the password).
Events (Outputs)
All three emit on every meaningful change.
| Output | Payload type | Fires when |
|---|---|---|
| strengthChange | { index: 0 \| 1 \| 2 \| 3; label: 'Weak' \| 'Fair' \| 'Good' \| 'Strong' } | The strength bucket changes (also on first render). |
| rulesChange | readonly PasswordRule[] | Any rule's met flag flips, or the rule list itself changes (e.g. config toggled). |
| validChange | boolean | true once every active rule is met; false otherwise. |
PasswordRule = { key: PasswordRuleKey; label: string; met: boolean }
PasswordRuleKey = 'length' \| 'noSpace' \| 'upper' \| 'lower' \| 'digit' \| 'special' \| 'noEmail' \| 'noUsername'
Reactive-forms validator
passwordValidator(config) is a synchronous ValidatorFn that applies the exact same rules as the component. The config is shallow-cloned at creation, so later mutations to your config object don't change validator behaviour.
import { FormControl } from '@angular/forms';
import { passwordValidator } from 'ngx-password-strength-validator';
const ctrl = new FormControl('', {
validators: [passwordValidator({ minLength: 12 })],
});
// ctrl.errors → { passwordRules: PasswordRuleKey[] } | nullFor UI/validator parity, pass the same config object reference to both passwordValidator() and <ngx-password-strength [config]>.
Theming (CSS variables)
The component exposes CSS custom properties on :host. Override them in any descendant stylesheet (no ::ng-deep required if you target the host element).
ngx-password-strength {
--nps-color-weak: #dc2626;
--nps-color-fair: #ea580c;
--nps-color-good: #ca8a04;
--nps-color-strong: #15803d;
--nps-color-empty: #e5e7eb;
--nps-bar-height: 0.5rem;
--nps-bar-radius: 0.25rem;
--nps-transition-ms: 150ms;
}Full variable list is in USER_GUIDE.md.
i18n
labels: PasswordStrengthLabels = {
length: (min, max) => max === undefined ? `Mindestens ${min} Zeichen` : `${min}–${max} Zeichen`,
noSpace: 'Keine Leerzeichen',
upper: 'Mindestens 1 Großbuchstabe',
// ... per-rule overrides ...
strength: { weak: 'Schwach', fair: 'OK', good: 'Gut', strong: 'Stark' },
};<ngx-password-strength [password]="pwd()" [config]="cfg" [labels]="labels" />License
MIT © atanupaul76
