File
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
Implements
Example
<common-password componentLabel="{{newPwdLabel}}"
[showPasswordStrength]="true"
[minLen]="pwdMinLen"
[pwdCriteria]="pwdValidChars"
[password]="data.password"
(passwordChange)="setNewPassword($event)"></common-password>
Index
Properties
|
|
Methods
|
|
Inputs
|
|
Outputs
|
|
HostListeners
|
|
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
|
|
pwdCriteria
|
Type : string | RegExp
|
|
showPasswordStrength
|
Type : boolean
|
Default value : false
|
|
Outputs
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
|
|
ngOnChanges
|
ngOnChanges(changes)
|
|
|
onInputBlur
|
onInputBlur($event)
|
|
|
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
|
|
Private
criteriaMsg
|
Type : string
|
Default value : ' contains invalid characters.'
|
|
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()
|
|
|
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 with directive