Password Strength

The <smart-password-strength> component renders a three-bar strength indicator with an optional hint list of unmet requirements. It follows the Base + Standard + Wrapper pattern with an InjectionToken-based extension mechanism. It renders a default PasswordStrengthStandardComponent which can be replaced via PASSWORD_STRENGTH_STANDARD_COMPONENT_TOKEN.


Usage

<input
  type="password"
  autocomplete="new-password"
  [value]="password()"
  (input)="onPasswordInput($event)"
/>
<smart-password-strength
  [passwordToCheck]="password()"
  [showHint]="showHint"
  (passwordStrength)="onPasswordStrength($event)"
/>

Components

PasswordStrengthComponent (<smart-password-strength>)

Main wrapper component. Renders PasswordStrengthStandardComponent by default. When PASSWORD_STRENGTH_STANDARD_COMPONENT_TOKEN is provided, renders the injected component via NgComponentOutlet. Forwards the passwordStrength output from the injected instance through its own output.

PasswordStrengthStandardComponent (<smart-password-strength-standard>)

Default concrete implementation. Renders:

  • three bars whose Tailwind classes come from barClasses() (filled-left-to-right by strength index),
  • a message <p> with a translation key INPUT.PASSWORD-STRENGTH.{poor|notGood|good} when applicable,
  • a hint <ul> (shown while showHint() is true) listing unmet requirements via INPUT.ERRORS.* keys,
  • dark-mode variants via smart:dark:* classes.

PasswordStrengthBaseComponent (abstract)

Abstract base directive for extending custom implementations. Exposes signal inputs, the output, the pure strength algorithm, and computed signals for classes and labels.

API

Inputs

InputTypeDefaultDescription
passwordToCheckInputSignal<string>requiredPassword value to evaluate
showHintInputSignal<boolean>requiredShow a hint list of unmet requirements
classInputSignal<string>''External CSS classes (alias for cssClass)

Outputs

OutputTypeDescription
passwordStrengthOutputEmitterRef<boolean>Emits true when strength is maximal (lower+upper+symbol+length), false otherwise.

Exposed base signals (available when extending the base)

SignalTypeDescription
result(){ lowerLetters; upperLetters; symbols; passLength }Flags for detected character classes and length threshold.
strength()number (0, 10, 20, 30)Numeric strength score matching the original algorithm.
strengthIndex()0 | 1 | 2 | 30=poor, 1=notGood, 2=good, 3=none/too-weak.
msg()'' | 'poor' | 'notGood' | 'good'Translation-key suffix for the message.
barClasses()string[] (length 3)Tailwind class string per bar.
msgClass()stringTailwind color class for the message <p>.
containerClasses()stringBase container classes with cssClass() appended.

PASSWORD_STRENGTH_STANDARD_COMPONENT_TOKEN

InjectionToken that allows replacing the default PasswordStrengthStandardComponent with a custom implementation. Provide a Type<PasswordStrengthBaseComponent> to override.

Extending the base class

import {
  ChangeDetectionStrategy,
  Component,
  computed,
  input,
  signal,
  ViewEncapsulation,
} from '@angular/core';

import {
  PASSWORD_STRENGTH_STANDARD_COMPONENT_TOKEN,
  PasswordStrengthBaseComponent,
  PasswordStrengthComponent,
} from '@smartsoft001/angular';

const VERDICTS: Record<string, string> = {
  poor: 'Poor',
  notGood: 'Could be better',
  good: 'Strong',
};

@Component({
  selector: 'docs-custom-password-strength',
  template: `
    <div [class]="containerClasses()">
      <div class="docs-password-strength__bars">
        @for (barClass of barClasses(); track $index) {
          <span class="docs-password-strength__bar" [class]="barClass"></span>
        }
      </div>

      @if (verdict()) {
        <p class="docs-password-strength__msg" [class]="msgClass()">
          {{ verdict() }}
        </p>
      }

      @if (showHint() && missing().length) {
        <ul class="docs-password-strength__hints">
          @for (requirement of missing(); track requirement) {
            <li class="docs-password-strength__hint-item">{{ requirement }}</li>
          }
        </ul>
      }
    </div>
  `,
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomPasswordStrengthComponent extends PasswordStrengthBaseComponent {
  // NgComponentOutlet passes 'cssClass' by canonical name, not the 'class' alias.
  override cssClass = input<string>('');

  // The base class already computes strength, barClasses, msgClass and
  // containerClasses, and emits passwordStrength from its own effect.
  readonly verdict = computed(() => VERDICTS[this.msg()] ?? '');

  readonly missing = computed(() => {
    const { lowerLetters, upperLetters, symbols, passLength } = this.result();
    return [
      lowerLetters ? '' : 'a lowercase letter',
      upperLetters ? '' : 'an uppercase letter',
      symbols ? '' : 'a special character',
      passLength ? '' : 'more than 6 characters',
    ].filter(Boolean);
  });
}

@Component({
  selector: 'docs-password-strength-custom-example',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [PasswordStrengthComponent],
  // The token swaps the standard meter for the custom one everywhere below
  // this component, so consumers keep writing `<smart-password-strength>`.
  providers: [
    {
      provide: PASSWORD_STRENGTH_STANDARD_COMPONENT_TOKEN,
      useValue: CustomPasswordStrengthComponent,
    },
  ],
  template: `
    <smart-password-strength
      [passwordToCheck]="password()"
      [showHint]="true"
      (passwordStrength)="strong.set($event)"
    />
  `,
})
export class PasswordStrengthCustomExampleComponent {
  readonly password = signal('abc');
  readonly strong = signal(false);
}

Translation Keys

The default template reads the following keys through TranslatePipe:

  • INPUT.PASSWORD-STRENGTH.poor — strength === 10
  • INPUT.PASSWORD-STRENGTH.notGood — strength === 20
  • INPUT.PASSWORD-STRENGTH.good — strength === 30
  • INPUT.ERRORS.invalidMinLength — shown when password length ≤ 6 (suffixed with 7)
  • INPUT.ERRORS.upperLetters — shown when no uppercase letter detected
  • INPUT.ERRORS.lowerLetters — shown when no lowercase letter detected
  • INPUT.ERRORS.symbols — shown when no symbol detected

Source

The component lives in packages/shared/angular/src/lib/components/password-strength and is documented for Claude Code by the angular-components-password-strength skill.