The Validation Result Presenter Service is responsible for automatically displaying validation error messages in the DOM. It creates and manages error containers, making it easy to show validation feedback to users without manual DOM manipulation.
Overview
When validation errors occur, the ValidationResultPresenterService automatically:
Creates error message containers in the DOM
Populates containers with error messages
Removes error messages when validation passes
Manages the lifecycle of error elements
This service works behind the scenes as a subscriber to the validation controller, responding to validation events automatically.
How It Works
The presenter service uses special data attributes to identify and manage validation error containers:
validation-result-id: Identifies individual error message elements
validation-result-container: Marks the container that holds error messages
When a validation error occurs for a form element, the service:
Finds the parent element of the validated input
Looks for an existing [validation-result-container] element
If not found, creates a new <div validation-result-container> element
Adds error messages as <span validation-result-id="{id}"> elements inside the container
Default Behavior
By default, when you use the & validate binding behavior, error messages are automatically displayed:
When validation fails, the DOM will automatically look like this:
Styling Error Containers
You can style the auto-generated error containers using CSS:
Pre-creating Error Containers
Instead of letting the service auto-create containers, you can pre-create them in your markup for better control:
DOM Structure
Understanding the generated DOM structure is important for styling and customization:
Using the Service Directly
You can inject and use the ValidationResultPresenterService directly for custom error presentation:
Service API
The ValidationResultPresenterService implements the following interface:
Manually remove validation errors from a target element.
Parameters:
target: The DOM element to remove errors from
results: Array of ValidationResult objects to remove
getValidationMessageContainer(target: Element): Element | null
Get or create the validation message container for a target element.
Parameters:
target: The validated input element
Returns: The container element, or null if the target has no parent
Behavior:
Searches for existing [validation-result-container] in the parent element
If not found, creates a new <div validation-result-container>
Appends the new container to the target's parent element
Custom Presenter Implementation
You can create a custom presenter by implementing the ValidationResultsSubscriber interface:
Register and use your custom presenter:
Integration with validation-errors Attribute
The presenter service works alongside the validation-errors custom attribute, which provides programmatic access to errors. See the Displaying Errors documentation for more information on using validation-errors.
Advanced Scenarios
Grouping Errors
Display all errors in a central location instead of next to each input:
Conditional Error Display
Show errors only after the user has attempted to submit:
Important Notes
The presenter service is automatically registered when you use ValidationHtmlConfiguration
Error containers are created in the parent element of the validated input
Each error message has a unique validation-result-id based on the ValidationResult's internal ID
The service automatically handles adding and removing error messages as validation state changes
Empty error containers remain in the DOM after errors are cleared (they can be hidden with CSS)
<!-- my-form.html -->
<form>
<div>
<input type="text" value.bind="username & validate" placeholder="Username">
<!-- Error container will be auto-created here if validation fails -->
</div>
<div>
<input type="email" value.bind="email & validate" placeholder="Email">
<!-- Error container will be auto-created here if validation fails -->
</div>
</form>
// my-form.ts
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 email: string = '';
public constructor() {
this.validationRules
.on(this)
.ensure('username')
.required()
.minLength(3)
.ensure('email')
.required()
.email();
}
}
<div>
<input type="text" value="ab" placeholder="Username">
<div validation-result-container>
<span validation-result-id="1">Username must be at least 3 characters.</span>
</div>
</div>
/* Target the error container */
[validation-result-container] {
margin-top: 4px;
padding: 8px;
background-color: #fee;
border: 1px solid #fcc;
border-radius: 4px;
}
/* Target individual error messages */
[validation-result-id] {
display: block;
color: #c00;
font-size: 0.875rem;
margin: 2px 0;
}
/* Show only the first error if you have multiple */
[validation-result-id]:not(:first-child) {
display: none;
}