A util file is added to forms test package: - it exposes simpleAsyncValidator, asyncValidator and asyncValidatorReturningObservable validators - it refactors simpleAsyncValidator and asyncValidator to use common promise creation code - it exposes currentStateOf allowing to get the validation state of a list of AbstractControl Closes #37831 PR Close #38020
		
			
				
	
	
		
			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;
 | |
| }
 |