88 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			88 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | /** | ||
|  |  * @license | ||
|  |  * Copyright Google LLC All Rights Reserved. | ||
|  |  * | ||
|  |  * Use of this source code is governed by an MIT-style license that can be | ||
|  |  * found in the LICENSE file at https://angular.io/license
 | ||
|  |  */ | ||
|  | 
 | ||
|  | import {EventEmitter} from '@angular/core'; | ||
|  | import {AbstractControl, AsyncValidatorFn, ValidationErrors} from '@angular/forms'; | ||
|  | import {of} from 'rxjs'; | ||
|  | 
 | ||
|  | function createValidationPromise( | ||
|  |     result: ValidationErrors|null, timeout: number): Promise<ValidationErrors|null> { | ||
|  |   return new Promise(resolve => { | ||
|  |     if (timeout == 0) { | ||
|  |       resolve(result); | ||
|  |     } else { | ||
|  |       setTimeout(() => { | ||
|  |         resolve(result); | ||
|  |       }, timeout); | ||
|  |     } | ||
|  |   }); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Returns a promise-based async validator that emits, after a delay, either: | ||
|  |  *  - an error `{async: true}` if the control value does not match the expected value | ||
|  |  *  - or null, otherwise | ||
|  |  *  The delay is either: | ||
|  |  *  - defined in `timeouts` parameter, as the association to the control value | ||
|  |  *  - or 0ms otherwise | ||
|  |  * | ||
|  |  * @param expected The expected control value | ||
|  |  * @param timeouts A dictionary associating a control value to when the validation will trigger for | ||
|  |  *     that value | ||
|  |  */ | ||
|  | export function asyncValidator(expected: string, timeouts = {}): AsyncValidatorFn { | ||
|  |   return (control: AbstractControl) => { | ||
|  |     const timeout = (timeouts as any)[control.value] ?? 0; | ||
|  |     const result = control.value != expected ? {async: true} : null; | ||
|  |     return createValidationPromise(result, timeout); | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Returns an async validator that emits null or a custom error after a specified delay. | ||
|  |  * If the delay is set to 0ms, the validator emits synchronously. | ||
|  |  * | ||
|  |  * @param timeout Indicates when the validator will emit | ||
|  |  * @param shouldFail When true, a validation error is emitted, otherwise null is emitted | ||
|  |  * @param customError When supplied, overrides the default error `{async: true}` | ||
|  |  */ | ||
|  | export function simpleAsyncValidator({ | ||
|  |   timeout = 0, | ||
|  |   shouldFail, | ||
|  |   customError = | ||
|  |   { | ||
|  |     async: true | ||
|  |   } | ||
|  | }: {timeout?: number, shouldFail: boolean, customError?: any}): AsyncValidatorFn { | ||
|  |   const result = shouldFail ? customError : null; | ||
|  |   return (c: AbstractControl) => | ||
|  |              timeout === 0 ? of(result) : createValidationPromise(result, timeout); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Returns the asynchronous validation state of each provided control | ||
|  |  * @param controls A collection of controls | ||
|  |  */ | ||
|  | export function currentStateOf(controls: AbstractControl[]): | ||
|  |     {errors: any; pending: boolean; status: string;}[] { | ||
|  |   return controls.map(c => ({errors: c.errors, pending: c.pending, status: c.status})); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Returns an `EventEmitter` emitting the default error `{'async': true}` | ||
|  |  * | ||
|  |  * @param c The control instance | ||
|  |  */ | ||
|  | export function asyncValidatorReturningObservable(c: AbstractControl): EventEmitter<any> { | ||
|  |   const e = new EventEmitter(); | ||
|  |   Promise.resolve(null).then(() => { | ||
|  |     e.emit({'async': true}); | ||
|  |   }); | ||
|  |   return e; | ||
|  | } |