File

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

Extends

AbstractFormControl

Implements

OnInit ControlValueAccessor

Metadata

selector common-phn
styleUrls ./phn.component.scss
templateUrl ./phn.component.html

Index

Properties
Methods
Inputs
Outputs
Accessors

Constructor

constructor(controlDir: NgControl)
Parameters :
Name Type Optional
controlDir NgControl No

Inputs

isBCPhn
Type : boolean
Default value : true
label
Type : string
Default value : 'Personal Health Number (PHN)'
labelforId
Type : string
Default value : 'phn_' + this.objectId
placeholder
Type : string
Default value : '1111 111 111'
required
Type : boolean
Default value : false
value
Type : string
disabled
Type : boolean
Default value : false
Inherited from AbstractFormControl
errorMessage
Type : ErrorMessage
Inherited from AbstractFormControl
label
Type : string
Inherited from AbstractFormControl

Outputs

blur
Type : EventEmitter<any>
valueChange
Type : EventEmitter<string>

Methods

ngOnInit
ngOnInit()
Returns : void
onBlur
onBlur(event: any)
Parameters :
Name Type Optional
event any No
Returns : void
onValueChange
onValueChange(value: any)
Parameters :
Name Type Optional
value any No
Returns : void
Private validatePhn
validatePhn()
Returns : ValidationErrors | null
Private validateSelf
validateSelf()
Returns : ValidationErrors | null
writeValue
writeValue(value: any)
Parameters :
Name Type Optional
value any No
Returns : void
ngOnInit
ngOnInit()
Inherited from AbstractFormControl
Returns : void
registerOnChange
registerOnChange(fn: any)
Inherited from AbstractFormControl
Parameters :
Name Type Optional
fn any No
Returns : void
registerOnTouched
registerOnTouched(fn: any)
Inherited from AbstractFormControl
Parameters :
Name Type Optional
fn any No
Returns : void
Protected registerValidation
registerValidation(ngControl: NgControl, fn: ValidationErrors)
Inherited from AbstractFormControl

Register self validating method

Parameters :
Name Type Optional Description
ngControl NgControl No
fn ValidationErrors No

function for validating self

Returns : any
setDisabledState
setDisabledState(isDisabled: boolean)
Inherited from AbstractFormControl
Parameters :
Name Type Optional
isDisabled boolean No
Returns : void
Protected setErrorMsg
setErrorMsg()
Inherited from AbstractFormControl
Returns : void
Private validateLabel
validateLabel()
Inherited from AbstractFormControl
Returns : void
Abstract writeValue
writeValue(value: any)
Inherited from AbstractFormControl
Parameters :
Name Type Optional
value any No
Returns : void

Properties

_defaultErrMsg
Type : ErrorMessage
Default value : { required: `${LabelReplacementTag} is required.`, invalid: `${LabelReplacementTag} is invalid.`, duplicate: `${LabelReplacementTag} was already used for another family member.`, }
Public controlDir
Type : NgControl
Decorators :
@Optional()
@Self()
mask
Type : any
phn
Type : string
Default value : ''
Abstract _defaultErrMsg
Type : ErrorMessage
Default value : {}
Inherited from AbstractFormControl
_onChange
Default value : () => {...}
Inherited from AbstractFormControl
_onTouched
Default value : () => {...}
Inherited from AbstractFormControl
Public objectId
Type : string
Default value : UUID.UUID()
Inherited from Base
Defined in Base:11

An identifier for parents to keep track of components

Accessors

value
getvalue()
setvalue(val: string)
Parameters :
Name Type Optional
val string No
Returns : void
import { Component, EventEmitter, Input, Output, Optional, Self, OnInit} from '@angular/core';
import { NUMBER, SPACE } from '../../models/mask.constants';
import { ControlValueAccessor, NgControl, ValidationErrors } from '@angular/forms';
import { ErrorMessage, LabelReplacementTag } from '../../models/error-message.interface';
import { AbstractFormControl } from '../../models/abstract-form-control';

@Component({
  selector: 'common-phn',
  templateUrl: './phn.component.html',
  styleUrls: ['./phn.component.scss']
})
export class PhnComponent extends AbstractFormControl implements OnInit, ControlValueAccessor {

  @Input() label: string = 'Personal Health Number (PHN)';
  @Input() placeholder: string = '1111 111 111';
  @Input() labelforId: string = 'phn_' + this.objectId;
  @Input() required: boolean = false;

  // Self-Validation inputs
  @Input() isBCPhn: boolean = true;

  _defaultErrMsg: ErrorMessage = {
    required: `${LabelReplacementTag} is required.`,
    invalid: `${LabelReplacementTag} is invalid.`,
    duplicate: `${LabelReplacementTag} was already used for another family member.`,
  };

  @Input()
  set value( val: string ) {
    if ( val) {
      this.phn = val;
    }
  }
  get value() {
    return this.phn;
  }

  @Output() valueChange: EventEmitter<string> = new EventEmitter<string>();
  @Output() blur: EventEmitter<any> = new EventEmitter<any>();

  phn: string = '';
  mask: any;

  constructor( @Optional() @Self() public controlDir: NgControl ) {
    super();
    if ( controlDir ) {
      controlDir.valueAccessor = this;
    }

    this.mask =
      [NUMBER, NUMBER, NUMBER, NUMBER, SPACE, NUMBER, NUMBER, NUMBER, SPACE, NUMBER, NUMBER, NUMBER];
  }

  ngOnInit() {
    super.ngOnInit();

    this.registerValidation( this.controlDir, this.validateSelf );
  }

  onValueChange( value: any ) {

    if ( value !== this.phn ) { // IE fix when focus does not display required error
      this.phn = value;
      this._onChange( value );
      this.valueChange.emit( value );
    }
  }

  onBlur( event: any ) {
    this._onTouched( event );
    this.blur.emit( event );
  }

  writeValue( value: any ): void {
    if ( value !== undefined ) {
      this.phn = value;
    }
  }

  private validateSelf(): ValidationErrors | null {

    const validatePhnResult = this.validatePhn();
    if ( validatePhnResult ) {
      return validatePhnResult;
    }
    return null;
   }

  private validatePhn(): ValidationErrors | null {

    if ( this.phn && this.phn.trim().length > 0 ) {

      // Init weights and other stuff
      const weights: number[] = [-1, 2, 4, 8, 5, 10, 9, 7, 3, -1];
      let sumOfRemainders = 0;

      // Clean up string
      const value = this.phn.trim();
      this.phn = value
                  .replace( /^0+/, '' ) // remove leading zeros
                  .replace(/_/g, '') // remove underlines
                  .replace(/\s/g, ''); // spaces

      // Test for length
      if (this.phn.length !== 10) {
        return { 'invalid': true };
      }
      // Look for a number that starts with 9 if BC only
      if (this.isBCPhn && this.phn[0] !== '9') {
        return { 'invalid': true };
      } else if (!this.isBCPhn && this.phn[0] === '9') { // Number cannot have 9
        return { 'invalid': true };
      }

      // Walk through each character
      for (let i = 0; i < this.phn.length; i++) {

        // pull out char
        const char = this.phn.charAt(i);

        // parse the number
        const num = Number(char);

        if (Number.isNaN(num)) {
          return { 'invalid': true };
        }

        // Only use the multiplier if weight is greater than zero
        let result = 0;
        if (weights[i] > 0) {
          // multiply the value against the weight
          result = num * weights[i];

          // divide by 11 and save the remainder
          result = result % 11;

          // add it to our sum
          sumOfRemainders += result;
        }
      }

      // mod by 11
      const checkDigit = 11 - (sumOfRemainders % 11);

      // if the result is 10 or 11, it is an invalid PHN
      if (checkDigit === 10 || checkDigit === 11) {
        return { 'invalid': true };
      }

      // Compare against 10th digitfinalDigit
      const finalDigit = Number(this.phn.substring(9, 10));
      if (checkDigit !== finalDigit) {
        return { 'invalid': true };
      }
    }
    return null;
  }


}

<label for="{{labelforId}}" class="control-label">{{label}}</label>
<input class="form-control"
       spellcheck="false"
       id="{{labelforId}}"
       [ngModel]="phn"
       (ngModelChange)="onValueChange($event)"
       (blur)="onBlur($event)"
       [placeholder]="placeholder"
       [textMask]="{mask: mask}"
       [disabled]="disabled"
       [required]="required"
       autocomplete="off"/>


  <!-- Error messages for input -->
  <common-error-container
    [displayError]="controlDir && !disabled && (controlDir.touched || controlDir.dirty) && controlDir?.errors">
    <div *ngIf="controlDir?.errors?.required">
      {{_defaultErrMsg.required}}
    </div>
    <div *ngIf="controlDir?.errors?.invalid">
      {{_defaultErrMsg.invalid}}
    </div>
    <div *ngIf="controlDir?.errors?.duplicate">
      {{_defaultErrMsg.duplicate}}
    </div>
  </common-error-container>
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""