Reputation: 385
I have a problem with an input validation using the aurelia-validation plugin.
The property bound that I want to validate is a property of an object (that is sometimes null) and it is inside an if.bind on this object.
Here is my code:
<div class="well" if.bind="selectedBody">
<input type="text" class="input-sm" class="form-control" value.bind="selectedBody.name & validate" required pattern="[a-z]+[aA-zZ|0-9]*">
<ul if.bind="controller.errors">
<li repeat.for="error of controller.errors">
${error.message}
</li>
</ul>
</div>
and my ViewModel constructor:
constructor(private ea : EventAggregator, private controllerFactory: ValidationControllerFactory) {
this.controller = controllerFactory.createForCurrentScope();
ValidationRules.ensure('selectedBody.name').required().withMessage("Sprite name is required").on(this);
}
I tried to replace the validation rule by:
ValidationRules.ensure('name').required().withMessage("Sprite name is required").on(this.selectedBody);
but then I need to set my object to an empty object rather than to null and validation doesn't work after the div is hided then shown again.
Upvotes: 0
Views: 912
Reputation: 1
Your self-answered question was helpful to me and I have to post this as an answer because I don't have any StackOverflow points so comment is blocked.
I had run into the same problem you had and was searching for an answer when I found your post. Based on your research, I tried several events and couldn't find anything that only attached the listener once.
I am having a difficult time finding working and complete Aurelia examples so I am posting this to give an alternative. With only about a week of experience using Aurelia and TypeScript this is probably a flawed example but hopefully someone find this useful.
import { inject } from 'aurelia-framework';
import { Tool } from './Tool';
import { ToolingService } from './ToolingService';
import { ValidationControllerFactory, ValidationRules, ValidationController } from 'aurelia-validation';
@inject(ValidationControllerFactory, ToolingService)
export class ToolDetail {
public tool: Tool;
public controller: ValidationController;
constructor(private validationControllerFactory: ValidationControllerFactory, private toolingService: ToolingService) {
this.controller = validationControllerFactory.createForCurrentScope();
}
attachValidation(tool: Tool) {
ValidationRules.ensure('toolType').required().on(this.tool)
.ensure('size').required().on(this.tool)
.ensure('code').required().maxLength(15).on(this.tool)
.ensure('alternateCode').required().maxLength(15).on(this.tool);
return tool;
}
activate(parms, routeConfig) {
return this.toolingService.getById(parms.id)
.then(tool => this.tool = tool)
.then(tool => { this.attachValidation(this.tool) });
}
}
That is calling a method like this:
import { HttpClient } from 'aurelia-fetch-client';
import { NewInstance, inject } from 'aurelia-framework';
import { Tool } from './Tool';
@inject(NewInstance.of(HttpClient))
export class ToolingService {
constructor(private http: HttpClient) {
http.configure(config => {
config.useStandardConfiguration()
.withBaseUrl('/api/Tooling/Tool/');
});
}
getById(id: string): Promise<Tool> {
return this.http.fetch(id)
.then(result => result.json() as Promise<Tool>)
.catch(error => console.log(error));
}
}
Upvotes: 0
Reputation: 385
Someone helped me solve my problem on the aurelia gitter (which I highly recommend!)
The solution was to move the validation rule in a property change listener method:
selectedBodyChanged(oldval, newval) {
if (this.controller.errors) {
this.controller.reset();
}
ValidationRules.ensure('name').required().withMessage("Sprite name is required").on(this.selectedBody);
}
I reset the controller to flush the validation errors displayed by previous selectedBody objects.
Upvotes: 1