File

projects/i-components/src/lib/utils/validation-helper.ts

Description

Provides a mechanism to display error messages linked to a specific DOM element.

Index

Properties
Methods

Constructor

constructor(elementRef: ElementRef, injectorBase: Injector)

Creates an instance of ValidationHelper.

Parameters :
Name Type Optional
elementRef ElementRef<HTMLElement> No
injectorBase Injector No

Properties

Private focusInListener
Type : function
Default value : null

Listener of the focus-in on the owner element to show the validation message.

Private focusOutListener
Type : function
Default value : null

Listener of the focus-out on the owner element to hide the validation message.

Public isRounded
Default value : false

Used to determine if validation should be displayed rounded or not.

Private messageToShow
Type : string
Default value : null

Current message to show on mouse over or on focus.

Private mouseLeaveListener
Type : function
Default value : null

Listener of the mouse leave on the corner div to hide the validation message.

Private mouseOverListener
Type : function
Default value : null

Listener of the mouse over the corner div to show the validation message.

Private ownerTarget
Type : HTMLElement
Default value : null

Reference to the owner being targeted to show the validation messages.

Private renderer2
Type : Renderer2

Angular's Renderer2.

Private validationMessageInstance
Type : any
Default value : null

Reference to the current validation message instance being shown.

Methods

Protected createCornerDiv
createCornerDiv(size: string)

Creates the corner div that will work as a visual clue to see validations message.

Parameters :
Name Type Optional
size string No
Returns : HTMLDivElement

{HTMLDivElement}

Protected hideValidationMessage
hideValidationMessage()

Hides the current validation message.

Returns : void
Public registerValidationMsgService
registerValidationMsgService(message: string, size: string, applyTo?: string, initiallyHide)

Register the validation message service with the owner target to provide the popup and other visual cues of the error.

Parameters :
Name Type Optional Default value
message string No
size string No '7px'
applyTo string Yes
initiallyHide No false
Returns : void

{void}

Protected showValidationMessage
showValidationMessage()

Shows the current validation message.

Returns : void
Public unregisterValidationMsgService
unregisterValidationMsgService()

Unregister the validation message service and executes a clean up of other elements.

Returns : void
Public updateValidationMsgService
updateValidationMsgService(message: string, size: string, applyTo: string)

It updates the informationg used by the validation directive given a registration already exists.

Parameters :
Name Type Optional
message string No
size string No
applyTo string No
Returns : void
import {
  ApplicationRef,
  ComponentFactoryResolver,
  ElementRef,
  Injector,
  Renderer2,
  ViewContainerRef,
} from '@angular/core';
import { ValidationMessageServiceComponent } from '../components/validation-message-service/validation-message-service.component';

/**
 * Provides a mechanism to display error messages linked to a specific DOM element.
 *
 * @export
 * @class ValidationHelper
 */
export class ValidationHelper {
  /**
   * Current message to show on mouse over or on focus.
   *
   * @private
   * @type {string}
   * @memberof ValidationHelper
   */
  private messageToShow: string = null;

  /**
   * Reference to the current validation message instance being shown.
   *
   * @private
   * @type {*}
   * @memberof ValidationHelper
   */
  private validationMessageInstance: any = null;

  /**
   * Reference to the owner being targeted to show the validation messages.
   *
   * @private
   * @type {HTMLElement}
   * @memberof ValidationHelper
   */
  private ownerTarget: HTMLElement = null;

  /**
   * Angular's Renderer2.
   *
   * @private
   * @type {Renderer2}
   * @memberof ValidationHelper
   */
  private renderer2: Renderer2;

  /**
   * Used to determine if validation should be displayed rounded or not.
   *
   * @public
   * @type {boolean}
   * @memberof ValidationHelper
   */
  public isRounded = false;

  /**
   * Listener of the mouse over the corner div to show the validation message.
   *
   * @private
   * @memberof ValidationHelper
   */
  private mouseOverListener: () => void = null;

  /**
   * Listener of the mouse leave on the corner div to hide the validation message.
   *
   * @private
   * @memberof ValidationHelper
   */
  private mouseLeaveListener: () => void = null;

  /**
   * Listener of the focus-in on the owner element to show the validation message.
   *
   * @private
   * @memberof ValidationHelper
   */
  private focusInListener: () => void = null;

  /**
   * Listener of the focus-out on the owner element to hide the validation message.
   *
   * @private
   * @memberof ValidationHelper
   */
  private focusOutListener: () => void = null;

  /**
   * Creates an instance of ValidationHelper.
   *
   * @param {ElementRef<HTMLElement>} elementRef
   * @param {Injector} injectorBase
   * @memberof ValidationHelper
   */
  constructor(
    private elementRef: ElementRef<HTMLElement>,
    private injectorBase: Injector
  ) {
    this.renderer2 = injectorBase.get(Renderer2);
  }

  /**
   * Register the validation message service with the owner target
   * to provide the popup and other visual cues of the error.
   *
   * @param {string} message
   * @param {string} [size='7px']
   * @param {string} [applyTo]
   * @param {boolean} [initiallyHide=false]
   * @return {*}  {void}
   * @memberof ValidationHelper
   */
  public registerValidationMsgService(
    message: string,
    size = '7px',
    applyTo?: string,
    initiallyHide = false
  ): void {
    /* istanbul ignore else */
    if (this.ownerTarget != null) {
      this.updateValidationMsgService(message, size, applyTo);
      return;
    }

    this.unregisterValidationMsgService();
    this.ownerTarget =
      applyTo != null
        ? this.elementRef.nativeElement.querySelector(applyTo)
        : this.elementRef.nativeElement;

    /* istanbul ignore else */
    if (!!this.ownerTarget) {
      // Add border to indicate an error.
      this.isRounded
        ? this.ownerTarget.classList.add('validationBorderErrorRounded')
        : this.ownerTarget.classList.add('validationBorderError');

      // Add corner cue.
      const cornerDiv = this.createCornerDiv(size);
      this.ownerTarget.appendChild(cornerDiv);

      this.messageToShow = message;
      this.mouseOverListener = this.renderer2.listen(
        cornerDiv,
        'mouseover',
        this.showValidationMessage.bind(this)
      );
      this.focusInListener = this.renderer2.listen(
        this.ownerTarget,
        'focusin',
        this.showValidationMessage.bind(this)
      );
      this.mouseLeaveListener = this.renderer2.listen(
        cornerDiv,
        'mouseleave',
        this.hideValidationMessage.bind(this)
      );
      this.focusOutListener = this.renderer2.listen(
        this.ownerTarget,
        'focusout',
        this.hideValidationMessage.bind(this)
      );

      /* istanbul ignore else */
      if (!initiallyHide && this.ownerTarget.contains(document.activeElement)) {
        // Currently the element has the focus.
        this.showValidationMessage();
      }
    }
  }

  /**
   * It updates the informationg used by the validation directive
   * given a registration already exists.
   *
   * @param {string} message
   * @param {string} size
   * @param {string} applyTo
   * @memberof ValidationHelper
   */
  public updateValidationMsgService(
    message: string,
    size: string,
    applyTo: string
  ): void {
    this.messageToShow = message;
    /* istanbul ignore else */
    if (this.validationMessageInstance != null) {
      this.validationMessageInstance.instance.message = this.messageToShow;
      this.validationMessageInstance.changeDetectorRef.detectChanges();
    }
  }

  /**
   * Unregister the validation message service and executes
   * a clean up of other elements.
   *
   * @memberof ValidationHelper
   */
  public unregisterValidationMsgService(): void {
    let validationBorderError = 'validationBorderError';
    let validationCornerError = '.validationCornerError';
    if (this.isRounded) {
      validationBorderError = 'validationBorderErrorRounded';
      validationCornerError = '.validationCornerErrorRounded';
    }
    this.ownerTarget?.classList.remove(validationBorderError);
    const cornerDiv = this.ownerTarget?.querySelector(validationCornerError);
    cornerDiv?.remove();
    this.ownerTarget = null;
    this.messageToShow = null;

    this.mouseOverListener?.();
    this.mouseOverListener = null;
    this.mouseLeaveListener?.();
    this.mouseLeaveListener = null;
    this.focusInListener?.();
    this.focusInListener = null;
    this.focusOutListener?.();
    this.focusOutListener = null;

    this.hideValidationMessage();
  }

  /**
   * Shows the current validation message.
   *
   * @protected
   * @return {*}
   * @memberof ValidationHelper
   */
  protected showValidationMessage() {
    /* istanbul ignore else */
    if (this.validationMessageInstance) {
      return;
    }

    const appRef = this.injectorBase.get(ApplicationRef);
    const factoryResolver = this.injectorBase.get(ComponentFactoryResolver);
    const root = appRef.components[0];
    const appRootViewContainer = root.injector.get(ViewContainerRef);
    const popupHostFactory = factoryResolver.resolveComponentFactory(
      ValidationMessageServiceComponent
    );
    const popupHostComponentRef = popupHostFactory.create(root.injector);
    appRootViewContainer.insert(popupHostComponentRef.hostView);

    this.validationMessageInstance = popupHostComponentRef;
    this.validationMessageInstance.instance.ownerTargetRect =
      this.ownerTarget.getBoundingClientRect();
    this.validationMessageInstance.instance.message = this.messageToShow;
    this.validationMessageInstance.changeDetectorRef.detectChanges();
  }

  /**
   * Hides the current validation message.
   *
   * @protected
   * @memberof ValidationHelper
   */
  protected hideValidationMessage() {
    this.validationMessageInstance?.destroy?.();
    this.validationMessageInstance?.changeDetectorRef?.detectChanges();
    this.validationMessageInstance = null;
  }

  /**
   * Creates the corner div that will work as a
   * visual clue to see validations message.
   *
   * @protected
   * @param {string} size
   * @return {*}  {HTMLDivElement}
   * @memberof ValidationHelper
   */
  protected createCornerDiv(size: string): HTMLDivElement {
    const div = document.createElement('div');
    this.isRounded
      ? div.classList.add('validationCornerErrorRounded')
      : div.classList.add('validationCornerError');
    div.style.width = size;
    div.style.height = size;
    return div;
  }
}

result-matching ""

    No results matching ""