import { AbstractControl , AsyncValidatorFn , Validator , Validators , ValidatorFn , } from '@angular/forms' ; import { Observable } from 'rxjs' ; export type ValidationResult = { [ validator ] : string | boolean ; } ; export type AsyncValidatorArray = Array < Validator | AsyncValidatorFn > ; export type ValidatorArray = Array < Validator | ValidatorFn > ; const normalizeValidator = ( validator ) : ValidatorFn | AsyncValidatorFn => { const func = ( validator as Validator ) . validate . bind ( validator ) ; if ( typeof func === 'function' ) { return ( c ) => func ( c ) ; } else { return < ValidatorFn | AsyncValidatorFn > validator ; } } ; export const composeValidators = ( validators ) : AsyncValidatorFn | ValidatorFn => { if ( validators == null || validators . length === 0 ) { return null ; } return Validators . compose ( validators . map ( normalizeValidator ) ) ; } ; export const validate = ( validators , asyncValidators ) => { return ( control ) => { const synchronousValid = ( ) => composeValidators ( validators ) ( control ) ; if ( asyncValidators ) { const asyncValidator = composeValidators ( asyncValidators ) ; return asyncValidator ( control ) . map ( v => { const secondary = synchronousValid ( ) ; if ( secondary || v ) { return Object . assign ( { } , secondary , v ) ; } } ) ; } if ( validators ) { return Observable . of ( synchronousValid ( ) ) ; } return Observable . of ( null ) ; } ; } ; export const message = ( validator , key ) : string => { switch ( key ) { case 'required' : return 'Please enter a value' ; case 'pattern' : return 'Value does not match required pattern' ; case 'minlength' : return 'Value must be N characters' ; case 'maxlength' : return 'Value must be a maximum of N characters' ; } switch ( typeof validator [ key ] ) { case 'string' : return < string > validator [ key ] ; default : return `Validation failed: ${ key }` ; } } ;