Aurelia's validation system is highly customizable, allowing you to configure validation behavior, replace core components, and customize how validation integrates with your application. This guide covers all available configuration options.
Overview
The validation system provides two levels of configuration:
Core Validation Configuration (ValidationConfiguration) - Configure the core validation engine
HTML Integration Configuration (ValidationHtmlConfiguration) - Configure how validation integrates with HTML/UI
Basic Configuration
Using Default Configuration
The simplest way to register validation is with the default configuration:
When to customize: Create a custom factory if you need to modify how validation controllers are instantiated or add custom behavior to all controllers.
Example:
Core Validation Options
These options configure the core validation engine and can be set using ValidationConfiguration or through ValidationHtmlConfiguration.
ValidatorType
Specifies the validator implementation to use.
Type:Class<IValidator>
Default:StandardValidator
When to customize: Create a custom validator if you need to modify core validation behavior or add custom validation processing logic.
Example:
MessageProviderType
Specifies the message provider implementation for validation error messages.
Type:Class<IValidationMessageProvider>
Default:ValidationMessageProvider
When to customize: Replace the message provider to customize how validation messages are parsed, interpolated, or retrieved.
Example:
CustomMessages
Provides custom messages for validation rules, either globally or for specific rules.
Type:ICustomMessage[]
Default:[]
Structure:
Example:
Messages can use interpolation:
${$displayName} - The display name of the property
Specifies the hydrator implementation for deserializing validation rules from data (e.g., JSON from a server).
Type:Class<IValidationExpressionHydrator>
Default:ModelValidationExpressionHydrator
When to customize: Replace the hydrator if you need to support a different rule serialization format or add support for custom rule types in model-based validation.
Example:
Complete Configuration Example
Here's a comprehensive example showing multiple customization options:
Per-Component Customization
You can also customize validation on a per-component basis by manually registering validation rules with custom settings:
import Aurelia from 'aurelia';
import { ValidationHtmlConfiguration } from '@aurelia/validation-html';
import { ValidationTrigger } from '@aurelia/validation-html';
import { MyApp } from './my-app';
Aurelia
.register(
ValidationHtmlConfiguration.customize((options) => {
// Change when validation triggers
options.DefaultTrigger = ValidationTrigger.change;
// Disable the validation-errors custom attribute
options.UseSubscriberCustomAttribute = false;
// Use a custom error container template
options.SubscriberCustomElementTemplate = `
<div class="custom-error-container">
<span class="error-icon">⚠</span>
<span class="error-text">\${error.result.message}</span>
</div>
`;
})
)
.app(MyApp)
.start();
ValidationHtmlConfiguration.customize((options) => {
// Validate immediately on every keystroke
options.DefaultTrigger = ValidationTrigger.change;
});
<!-- Use change trigger for this specific input -->
<input type="text" value.bind="username & validate:change">
<!-- Use manual trigger - only validate when controller.validate() is called -->
<input type="text" value.bind="email & validate:manual">
import {
IValidationMessageProvider,
ValidationMessageProvider,
IValidationRule
} from '@aurelia/validation';
import { Interpolation, PrimitiveLiteralExpression } from '@aurelia/expression-parser';
export class CustomMessageProvider extends ValidationMessageProvider {
public getMessage(rule: IValidationRule): Interpolation | PrimitiveLiteralExpression {
// Add custom logic for message retrieval
const message = super.getMessage(rule);
// You could modify messages, add prefixes, etc.
console.log('Getting message for rule:', rule);
return message;
}
}
ValidationHtmlConfiguration.customize((options) => {
options.MessageProviderType = CustomMessageProvider;
});
interface ICustomMessage {
rule?: string; // Rule name (e.g., 'required', 'email')
messageKey?: string; // Message key for the rule
message: string; // The custom message template
}
ValidationHtmlConfiguration.customize((options) => {
options.CustomMessages = [
// Override default "required" message
{
rule: 'required',
message: 'This field cannot be empty.'
},
// Override email validation message
{
rule: 'email',
message: 'Please provide a valid email address.'
},
// Custom message for specific messageKey
{
messageKey: 'minLength',
message: '${$displayName} needs at least ${$rule.length} characters.'
},
// Global fallback message
{
message: 'The value you entered is not valid.'
}
];
});
import Aurelia from 'aurelia';
import { ValidationHtmlConfiguration } from '@aurelia/validation-html';
import { ValidationTrigger } from '@aurelia/validation-html';
import { MyApp } from './my-app';
Aurelia
.register(
ValidationHtmlConfiguration.customize((options) => {
// HTML-specific options
options.DefaultTrigger = ValidationTrigger.changeOrFocusout;
options.UseSubscriberCustomAttribute = true;
options.SubscriberCustomElementTemplate = `
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle"></i>
\${error.result.message}
</div>
`;
// Core validation options
options.CustomMessages = [
{
rule: 'required',
message: '⚠ ${$displayName} is required.'
},
{
rule: 'email',
message: '📧 Please enter a valid email address.'
},
{
rule: 'minLength',
message: '${$displayName} must have at least ${$rule.length} characters.'
},
{
rule: 'maxLength',
message: '${$displayName} cannot exceed ${$rule.length} characters.'
},
{
rule: 'range',
message: '${$displayName} must be between ${$rule.min} and ${$rule.max}.'
}
];
// Use custom implementations if needed
// options.ValidatorType = CustomValidator;
// options.MessageProviderType = CustomMessageProvider;
// options.HydratorType = CustomHydrator;
// options.ValidationControllerFactoryType = CustomControllerFactory;
})
)
.app(MyApp)
.start();
import { newInstanceForScope, resolve } from '@aurelia/kernel';
import { IValidationRules } from '@aurelia/validation';
import { IValidationController } from '@aurelia/validation-html';
export class MyForm {
private validationController = resolve(newInstanceForScope(IValidationController));
private validationRules = resolve(IValidationRules);
public username: string = '';
public constructor() {
this.validationRules
.on(this)
.ensure('username')
.required()
.withMessage('Username cannot be empty!') // Custom message for this rule
.minLength(3)
.withMessage('Username too short - need at least 3 characters.');
}
}