Reputation: 4295
I am developing a custom element in aurelia. And trying to do validation on it. For example let's say I have a form which is in my app component and the validation rules and controller is defined inside this component like this:
@inject(NewInstance.of(ValidationController))
export class App {
constructor(validationController) {
this.validationController = validationController;
ValidationRules
.ensure('password')
.required()
.ensure('email')
.email()
.on(this);
}
clicked() {
this.validationController.validate().then(console.log);
}
}
and I have a custom element like this one:
<template class.bind="statusClasses" validation-errors.bind="inputErrors">
<input id.one-time="id" value.bind="value" type.bind="type" disabled.bind="disabled"
change.delegate="change({ value: value, $event: $event })" />
<label for.one-time="id">${label}</label>
<span class="help-block" repeat.for="errorInfo of inputErrors">
${errorInfo.error.message}
</span>
</template>
import { bindable, bindingMode, customElement, computedFrom } from 'aurelia-framework';
import './pa-au-md-input.css';
@customElement('pa-au-md-input')
export class PaAuMdInputCustomElement {
@bindable({ defaultBindingMode: bindingMode.twoWay }) value;
@bindable label;
@bindable doValidation = true;
@bindable showValidationErrors = true;
@bindable disabled = false;
@bindable type = 'text';
@bindable change = () => { console.debug(`change event of pa-au-md-input-${this.id} is un-used.`) };
static nextId = 0; // babel way of #1
constructor() {
this.initializeVariables();
}
initializeVariables() {
this.autoIncrementedId = PaAuMdInputCustomElement.nextId++;
this.id = `pa-au-md-input#${this.autoIncrementedId}`;
}
@computedFrom('disabled')
get statusClasses() {
return ''
+ (this.disabled ? 'disabled' : '')
+ (this.showValidationErrors && this.inputErrors && this.inputErrors.length ? 'has-error' : '');
}
}
and the usage of this custom element inside app.html
:
<template>
<p>
Usage: <code><pa-au-md-input label="some input label title" change.call="optionalChangeHandler(value, $event)" value.bind="optionalValueBind"/></code>
</p>
<pa-au-md-input label="password" value.bind="password & validate" type="password">
</pa-au-md-input>
<p>
Usage: <code><pa-au-md-input label="some input label title" change.call="optionalChangeHandler(value, $event)" value.bind="optionalValueBind"/></code>
</p>
<pa-au-md-input label="email" value.bind="email & validate" type="email"></pa-au-md-input>
<input type="password" value.bind="password & validate"/>
<button click.delegate="clicked()">validate</button>
</template>
Now, if I type some invalid email inside <pa-au-md-input label="email" value.bind="email & validate" type="email"></pa-au-md-input>
and then press the validate button, then it will be validated and everything will go right. But it does not check validation rules on blur event. While the input after that, <input type="password" value.bind="password & validate"/>
does validation on blur just right. So what is the problem and how to solve it?
Upvotes: 3
Views: 348
Reputation: 36
You need to forward the blur event of inner input to custom-element container (propagate it)
<input id.one-time="id" value.bind="value" type.bind="type" disabled.bind="disabled" blur.delegate="forwardEvent($event)" change.delegate="change({ value: value, $event: $event })" />
and the changes in the JS file
export class PaAuMdInputCustomElement {
// omited other codes
forwardEvent(event) {
this.element.dispatchEvent(clone(event));
}
}
const clone = e => new e.constructor(e.type, e);
I think this works fine.
Upvotes: 2