asyncValidators
Record<string, AsyncCustomValidator <unknown, unknown, unknown>> | undefined
Async custom validators using Angular's resource-based validateAsync() API
Angular's validateAsync uses the resource API for async validation. Validators must provide params, factory, onSuccess, and optional onError callbacks.
Structure:
params: Function that computes params from field contextfactory: Function that creates ResourceRef from params signalonSuccess: Maps resource result to validation errorsonError: Optional handler for resource errorsUse Cases:
Database lookups via services with resource API Complex async business logic with Angular resources Note: For HTTP validation, prefer httpValidators which provides a simpler API specifically designed for HTTP requests.
Example usage Database Lookup with Resource
asyncValidators : {
checkUsernameAvailable : {
params : ( ctx ) => ( { username : ctx . value () } ) ,
factory : ( params ) => {
const injector = inject ( Injector ) ;
return resource ( {
request : () => params () ,
loader : ({ request }) => {
if ( ! request ?. username ) return null;
const service = injector . get ( UserService ) ;
return firstValueFrom ( service . checkAvailability ( request . username )) ;
}
} ) ;
},
onSuccess : ( result , ctx ) => {
if ( ! result ) return null;
return result . available ? null : { kind : ' usernameTaken ' };
},
onError : ( error , ctx ) => {
console . error ( ' Availability check failed: ' , error ) ;
return null; // Don't block form on network errors
}
}
}
customFunctions
Record<string, CustomFunction > | undefined
Custom evaluation functions for conditional expressions.
Used for: when/readonly/disabled logic Return type: any value (typically boolean)
Example usage customFunctions : {
isAdult : ( context ) => context . age >= 18 ,
calculateAge : ( context ) => {
const birthDate = new Date ( context . birthDate ) ;
return new Date () . getFullYear () - birthDate . getFullYear () ;
}
}
httpValidators
Record<string, HttpCustomValidator <unknown, unknown>> | undefined
HTTP validators using Angular's validateHttp() API
Angular's validateHttp provides HTTP validation with automatic request cancellation and integration with the resource API.
Structure:
request: Function that returns URL string or HttpResourceRequestonSuccess: REQUIRED - Maps HTTP response to validation errors (inverted logic!)onError: Optional handler for HTTP errorsBenefits:
Automatic request cancellation when field value changes Built-in integration with Angular's resource management Simpler than asyncValidators for HTTP use cases Important: onSuccess uses inverted logic - it maps SUCCESSFUL HTTP responses to validation errors. For example, if the API returns { available: false }, your onSuccess should return { kind: 'usernameTaken' }.
Example usage Username Availability Check (GET)
httpValidators : {
checkUsername : {
request : ( ctx ) => {
const username = ctx . value () ;
if ( ! username ) return undefined; // Skip validation if empty
return ` /api/users/check-username?username= ${ encodeURIComponent (username) }` ;
},
onSuccess : ( response , ctx ) => {
// Inverted logic: successful response may indicate validation failure
return response . available ? null : { kind : ' usernameTaken ' };
},
onError : ( error , ctx ) => {
console . error ( ' Availability check failed: ' , error ) ;
return null; // Don't block form on network errors
}
}
}
Address Validation (POST with Body)
httpValidators : {
validateAddress : {
request : ( ctx ) => {
const zipCode = ctx . value () ;
if ( ! zipCode ) return undefined;
return {
url : ' /api/validate-address ' ,
method : ' POST ' ,
body : {
street : ctx . valueOf ( ' street ' as any ) ,
city : ctx . valueOf ( ' city ' as any ) ,
zipCode : zipCode
},
headers : { ' Content-Type ' : ' application/json ' }
};
},
onSuccess : ( response ) => {
return response . valid ? null : { kind : ' invalidAddress ' };
}
}
}
validators
Record<string, CustomValidator > | undefined
Custom validators using Angular's public FieldContext API
(ctx, params?) => ValidationError | ValidationError[] | null
Validators receive FieldContext which provides access to:
Current field value: ctx.value() Field state: ctx.state (errors, touched, dirty, etc.) Other field values: ctx.valueOf(path) - public API! Other field states: ctx.stateOf(path) Parameters from JSON configuration Return Types:
Single error: { kind: 'errorKind' } for field-level validation Multiple errors: [{ kind: 'error1' }, { kind: 'error2' }] for cross-field validation No error: null when validation passes Example usage Single Field Validation
validators : {
noSpaces : ( ctx ) => {
const value = ctx . value () ;
if ( typeof value === ' string ' && value . includes ( ' ' )) {
return { kind : ' noSpaces ' };
}
return null;
}
}
Cross-Field Validation (Public API)
validators : {
lessThan : ( ctx , params ) => {
const value = ctx . value () ;
const compareToPath = params ?. field as string ;
// Use valueOf() to access other field - public API!
const otherValue = ctx . valueOf ( compareToPath as any ) ;
if ( otherValue !== undefined && value >= otherValue ) {
return { kind : ' notLessThan ' };
}
return null;
}
}
Multiple Errors
validators : {
validateDateRange : ( ctx ) => {
const errors : ValidationError [] = [] ;
const startDate = ctx . valueOf ( ' startDate ' as any ) ;
const endDate = ctx . valueOf ( ' endDate ' as any ) ;
if ( ! startDate ) errors . push ( { kind : ' startDateRequired ' } ) ;
if ( ! endDate ) errors . push ( { kind : ' endDateRequired ' } ) ;
if ( startDate && endDate && startDate > endDate ) {
errors . push ( { kind : ' invalidDateRange ' } ) ;
}
return errors . length > 0 ? errors : null;
}
}