import { Injectable } from '@angular/core' ; import { NgForm , AbstractControl , ValidationErrors } from '@angular/forms' ; import { ThyFormValidatorLoader , ERROR_VALUE_REPLACE_REGEX } from './form-validator-loader' ; import { ThyFormValidatorConfig } from './form.class' ; import { Dictionary } from 'ngx-tethys/types' ; import { isUndefinedOrNull } from 'ngx-tethys/util' ; @ Injectable ( ) export class ThyFormValidatorService { private _ngForm : NgForm ; private _formElement : HTMLFormElement ; private _config : ThyFormValidatorConfig ; public errors : string [ ] = [ ] ; public validations : Dictionary < { hasError ? : boolean ; errorMessages ? : string [ ] ; } > = { } ; private _getElement ( name ) { const element = this . _formElement . elements [ name ] ; if ( element ) { return element ; } else { return this . _formElement . querySelector ( `[name='${ name }']` ) ; } } private _clearElementError ( name ) { if ( this . validations [ name ] && this . validations [ name ] . hasError ) { this . validations [ name ] . hasError = false ; this . validations [ name ] . errorMessages = [ ] ; this . thyFormValidateLoader . removeError ( this . _getElement ( name ) ) ; } } private _tryGetValidation ( name ) { if ( ! this . validations [ name ] ) { this . _initializeFormControlValidation ( name , this . _ngForm . controls [ name ] ) ; } return this . validations [ name ] ; } private _addError ( message ) { this . errors . unshift ( message ) ; } private _clearErrors ( ) { this . errors = [ ] ; } private _initializeFormControlValidation ( name , control ) { this . validations [ name ] = { hasError : false , errorMessages : [ ] } ; control . valueChanges . subscribe ( ( ) => { this . _clearElementError ( name ) ; this . _clearErrors ( ) ; } ) ; } private _restFormControlValidation ( name ) { const validation = this . validations [ name ] ; if ( validation ) { validation . hasError = false ; validation . errorMessages = [ ] ; } } private _formatValidationMessage ( name , message ) { const control = this . _ngForm . controls [ name ] ; if ( control ) { return message . replace ( ERROR_VALUE_REPLACE_REGEX , ( tag , key ) => { if ( key ) { return isUndefinedOrNull ( control . errors [ key ] [ key ] ) ? control . errors [ key ] . requiredLength : control . errors [ key ] [ key ] ; } } ) ; } else { return message ; } } private _getValidationMessage ( name , validationError ) { let message = null ; if ( this . _config && this . _config . validationMessages && this . _config . validationMessages [ name ] && this . _config . validationMessages [ name ] [ validationError ] ) { message = this . _config . validationMessages [ name ] [ validationError ] ; } else { message = this . thyFormValidateLoader . getErrorMessage ( name , validationError ) ; } return this . _formatValidationMessage ( name , message ) ; } private _getValidationMessages ( name , validationErrors ) { const messages = [ ] ; for ( const validationError in validationErrors ) { if ( validationErrors . hasOwnProperty ( validationError ) ) { messages . push ( this . _getValidationMessage ( name , validationError ) ) ; } } return messages ; } private _setControlValidationError ( name , errorMessages ) { const validation = this . _tryGetValidation ( name ) ; validation . errorMessages = errorMessages ; validation . hasError = true ; this . thyFormValidateLoader . showError ( this . _getElement ( name ) , errorMessages ) ; } constructor ( private thyFormValidateLoader ) { } initialize ( ngForm , formElement ) { this . _ngForm = ngForm ; this . _formElement = formElement ; } setValidatorConfig ( config ) { this . _config = config ; } validateControl ( name ) { this . _clearElementError ( name ) ; const control = this . _ngForm . controls [ name ] ; if ( control && control . invalid ) { const errorMessages = this . _getValidationMessages ( name , control . errors ) ; this . _setControlValidationError ( name , errorMessages ) ; } } validateControls ( ) { for ( const name in this . _ngForm . controls ) { if ( this . _ngForm . controls . hasOwnProperty ( name ) ) { this . _tryGetValidation ( name ) ; this . validateControl ( name ) ; } } const names = Object . keys ( this . validations ) ; names . forEach ( name => { if ( ! this . _ngForm . controls [ name ] ) { delete this . validations [ name ] ; } } ) ; } addError ( message ) { this . _addError ( message ) ; } validate ( $event ? ) { this . _ngForm . onSubmit ( $event ) ; this . validateControls ( ) ; return this . _ngForm . valid ; } reset ( ) { this . _ngForm . reset ( ) ; for ( const name in this . validations ) { if ( this . validations . hasOwnProperty ( name ) ) { this . _restFormControlValidation ( name ) ; this . _clearElementError ( name ) ; } } } setElementErrorMessage ( name , message ) { this . _clearElementError ( name ) ; this . _setControlValidationError ( name , [ message ] ) ; } }