File

projects/common/lib/components/password/password.component.ts

Description

PasswordComponent is a text input for a user's password. It includes:

  • A password strength bar
  • Minimum length validations

Note - if your application has requirements to check things like username is not present in password, we recommend doing this in the (passwordChange) callback.

Extends

Base

Implements

OnInit OnChanges

Example

<common-password componentLabel="{{newPwdLabel}}"
   [showPasswordStrength]="true"
   [minLen]="pwdMinLen"
   [pwdCriteria]="pwdValidChars"
   [password]="data.password"
   (passwordChange)="setNewPassword($event)"></common-password>

Metadata

selector common-password
styleUrls ./password.component.scss
templateUrl ./password.component.html
viewProviders { provide: ControlContainer, useExisting: forwardRef(() => NgForm) }

Index

Properties
Methods
Inputs
Outputs
HostListeners

Constructor

constructor()

Inputs

errorMessages
Type : PasswordErrorMsg
isDisabled
Type : boolean
Default value : false
isRequired
Type : boolean
Default value : true
label
Type : string
Default value : 'Password'
maxLen
Type : string
Default value : '32'
minLen
Type : string
Default value : '8'
objectID
Type : string
Default value : 'password_' + this.objectId
password
Type : string
pwdCriteria
Type : string | RegExp
showPasswordStrength
Type : boolean
Default value : false

Outputs

blurEvent
Type : EventEmitter
passwordChange
Type : EventEmitter<string>

HostListeners

document:paste
Arguments : '$event'
document:paste(event)

Methods

Private getPasswordStrength
getPasswordStrength(password: string)

Get the strength of the password

0 = too guessable: risky password. (guesses < 10^3)
1 = very guessable: protection from throttled online attacks. (guesses < 10^6)
2 = somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8)
3 = safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10)
4 = very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)

https://github.com/dropbox/zxcvbn

Parameters :
Name Type Optional
password string No
Returns : number
ngOnChanges
ngOnChanges(changes)
Parameters :
Name Optional
changes No
Returns : void
ngOnInit
ngOnInit()
Returns : void
onInputBlur
onInputBlur($event)
Parameters :
Name Optional
$event No
Returns : void
setPassword
setPassword(password: string)

Passes the value entered back to the calling component

Parameters :
Name Type Optional Description
password string No

value the was entered by

Returns : void

Properties

Private criteriaMsg
Type : string
Default value : ' contains invalid characters.'
Public errMsg
Type : PasswordErrorMsg
Public hideValue
Default value : true
Private minLenMsgSeg1
Type : string
Default value : ' must be at least '
Private minLenMsgSeg2
Type : string
Default value : ' characters in length.'
Public pswdStrength
Type : number
Private requiredMsgSeg
Type : string
Default value : ' is required.'
Public strengthPercentage
Type : number
Default value : 0
Public objectId
Type : string
Default value : UUID.UUID()
Inherited from Base
Defined in Base:11

An identifier for parents to keep track of components

Design Guidelines

Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente, magnam ipsam. Sit quasi natus architecto rerum unde non provident! Quia nisi facere amet iste mollitia voluptatem non molestias esse optio?

Aperiam fugiat consectetur temporibus, iste repellat, quisquam sapiente nisi distinctio optio, autem nemo tenetur error eum voluptatibus ab accusamus quis voluptatum blanditiis. Quam et ut reprehenderit vitae nobis, at ipsum!

Exercitationem pariatur animi repudiandae corporis obcaecati ratione ducimus beatae quam, nostrum magnam unde numquam quidem cupiditate odit id. Beatae alias molestiae, optio incidunt harum quia voluptates deserunt sequi. Nesciunt, optio.

import { Component, OnInit, Input, Output, EventEmitter, HostListener, OnChanges, forwardRef } from '@angular/core';
import { Base } from '../../models/base';
import { ControlContainer, NgForm } from '@angular/forms';
import * as zxcvbn_ from 'zxcvbn';
// Awkward necessary workaround due to bug in build tools
// https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207
const zxcvbn = zxcvbn_;


/**
 * TODO:  Convert to custom form control - remove ngForm
 */
/**
 * Interface for passing in error messages
 * Example:
 *  errorMessages = {
 *       required: this.componentLabel + ' is required.',
 *       minLength: this.componentLabel + ' must be ' + this.minLen + ' characters.',
 *       criteria: this.componentLabel + ' does not meet password criteria.'
 *     }
 */
export interface PasswordErrorMsg {
  required?: string;
  minLength?: string;
  criteria?: string;
}
/**
 * PasswordComponent is a text input for a user's password. It includes:
 *
 * - A password strength bar
 * - Minimum length validations
 *
 * Note - if your application has requirements to check things like username is not
 * present in password, we recommend doing this in the (passwordChange) callback.
 *
 * @example
 *       <common-password componentLabel="{{newPwdLabel}}"
 *                      [showPasswordStrength]="true"
 *                      [minLen]="pwdMinLen"
 *                      [pwdCriteria]="pwdValidChars"
 *                      [password]="data.password"
 *                      (passwordChange)="setNewPassword($event)"></common-password>
 *
 * @export
 */
@Component({
  selector: 'common-password',
  templateUrl: './password.component.html',
  styleUrls: ['./password.component.scss'],
  /* Re-use the same ngForm that it's parent is using. The component will show
   * up in its parents `this.form`, and will auto-update `this.form.valid`
   */
  viewProviders: [ { provide: ControlContainer, useExisting: forwardRef(() => NgForm ) } ]
})
export class PasswordComponent extends Base implements OnInit, OnChanges {

  // Inputs for the component
  @Input() label: string = 'Password';
  @Input() isRequired: boolean = true;
  @Input() isDisabled: boolean = false;
  @Input() password: string;
  @Input() pwdCriteria: string | RegExp;
  @Input() minLen: string  = '8';
  @Input() maxLen: string  = '32';
  @Input() errorMessages: PasswordErrorMsg;
  @Input() showPasswordStrength: boolean = false;
  @Input() objectID: string = 'password_' + this.objectId;


  // Output from the component
  @Output() passwordChange: EventEmitter<string> = new EventEmitter<string>();
  @Output() blurEvent = new EventEmitter();

  // Flag for the fa-eye to show or hide password
  public hideValue = true;
  public pswdStrength: number;
  public strengthPercentage = 0;

  public errMsg: PasswordErrorMsg;

  // default messages
  private requiredMsgSeg: string = ' is required.';
  private minLenMsgSeg1: string = ' must be at least ';
  private minLenMsgSeg2: string = ' characters in length.';
  private criteriaMsg: string = ' contains invalid characters.';


  constructor() {
    super();
  }

  ngOnInit() {

    // Set default messages
    this.errMsg =    {
      required: this.label + this.requiredMsgSeg,
      minLength: this.label + this.minLenMsgSeg1 + this.minLen + this.minLenMsgSeg2,
      criteria: this.label + this.criteriaMsg
    };

    // Replace default message if provided
    if ( this.errorMessages ) {

      if ( this.errorMessages.required ) {
        this.errMsg.required = this.errorMessages.required;
      }

      if ( this.errorMessages.minLength ) {
        this.errMsg.minLength = this.errorMessages.minLength;
      }

      if ( this.errorMessages.criteria ) {
        this.errMsg.criteria = this.errorMessages.criteria;
      }
    }
  }

  ngOnChanges(changes) {
    if (changes.password && this.password) {

      // Check strength of password
      this.pswdStrength = this.getPasswordStrength( this.password );
      this.strengthPercentage = ((this.pswdStrength + 1) / 5 ) * 100;
    }
  }

  /**
   * Passes the value entered back to the calling component
   * @param password value the was entered by
   */
  setPassword( password: string ) {
    this.passwordChange.emit( password );
  }

  onInputBlur($event) {
    this.blurEvent.emit( event );
  }

  // Prevent user from pasting data into the text box
  @HostListener( 'document:paste', ['$event'] )
  onPaste( event ) {
      return false;
  }

  /**
   * Get the strength of the password

   *    0 = too guessable: risky password. (guesses < 10^3)
   *    1 = very guessable: protection from throttled online attacks. (guesses < 10^6)
   *    2 = somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8)
   *    3 = safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10)
   *    4 = very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)
   *
   *  https://github.com/dropbox/zxcvbn
   */
  private getPasswordStrength( password: string ): number {
    // Password strength feedback
    const pswdFeedback = zxcvbn( password );
    return pswdFeedback.score;
  }
}
<label class="control-label" for="{{objectID}}">{{label}}</label>
<input #pswdRef="ngModel"
       type="{{hideValue? 'password': 'text'}}"
       class="form-control password-field"
       name="{{objectID}}"
       id="{{objectID}}"
       [ngModel]="password"
       (ngModelChange)="setPassword($event)"
       (blur)="onInputBlur($event)"
       [pattern]="pwdCriteria"
       [required]="isRequired"
       [minlength]="minLen"
       [maxlength]="maxLen"
       [disabled]="isDisabled"
       autocomplete="off"/>
<span class="fa fa-fw {{hideValue? 'fa-eye' : 'fa-eye-slash'}} password-field-icon"
      (click)='hideValue = !hideValue'></span>
<div *ngIf='password && showPasswordStrength'>
<!-- The progress bar -->
  <div class="progress password-strength-bar" >
    <div class="progress-bar {{pswdStrength >= 4? 'bg-success' : (pswdStrength >= 3? 'bg-warning' : 'bg-danger')}}"
        role="progressbar"
        [style.width]='strengthPercentage + "%"'
        [attr.aria-valuenow]="strengthPercentage"
        aria-valuemin="0"
        aria-valuemax="100">
    </div>
  </div>
  <span class="password-progress-label {{pswdStrength >= 4? 'text-success' : (pswdStrength >= 3? 'text-warning' : 'text-danger')}}"></span>
</div>
<!-- Error messages for component -->
<div *ngIf="!pswdRef.disabled && (pswdRef.touched || pswdRef.dirty)"
    role="alert"
    class='error-container'
    aria-live="assertive">
  <div class="text-danger" *ngIf="pswdRef?.errors?.required">
    {{errMsg.required}}
  </div>
  <div class="text-danger" *ngIf="pswdRef?.errors?.minlength">
      {{errMsg.minLength}}
  </div>
  <div class="text-danger" *ngIf="pswdRef?.errors?.pattern && !pswdRef?.errors?.minlength">
      {{errMsg.criteria}}
  </div>
</div>

Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""