Hi. I tried to simplify the html needed to create a form with fields+validation+error display by creating a custom component.
validated-input.html
<template>
<div class="form-input ${class}">
<slot name="icon"></slot>
<label if.bind="!floatingLabel">${label}</label>
<div>
<div class="ui input primary-input">
<input type="text" ref="field" class="${errors.length > 0 ? 'has-errors': ''}"
keydown.delegate="keyDownHandler($event)" value.bind="value" blur.trigger="blur()" input.trigger="input()" autocomplete="off">
<div if.bind="floatingLabel" class="floating-label"><span class="floating-label-focus">${label}</span></div>
</div>
<div if.bind="errors.length > 0" class="validation-error">
<i class="exclamation triangle icon"></i>
<span repeat.for="e of errors">${e.message}</span>
</div>
</div>
</div>
</template>
validated-input.ts
import { ValidationController, ValidateResult, validateTrigger } from "aurelia-validation";
import { customElement, bindable, containerless, autoinject, bindingMode, DOM } from "aurelia-framework";
@autoinject
@containerless
@customElement("validated-input")
export class ValidatedInput {
@bindable field: HTMLInputElement;
@bindable label: string;
@bindable class: string = "";
@bindable({ defaultBindingMode: bindingMode.twoWay }) value: string;
@bindable name: string;
@bindable floatingLabel: boolean = false;
@bindable validationTrigger: string = "change";
@bindable maxlength: string | null = null;
@bindable pattern: string | null = null;
errors: ValidateResult[];
private controller: ValidationController;
constructor(private element: Element) {
}
bind(bindingContext: any) {
this.field.setAttribute("value", this.value || "");
this.controller = bindingContext.controller;
if (this.maxlength) {
this.field.setAttribute("maxlength", this.maxlength);
}
if (this.pattern) {
this.field.setAttribute("pattern", this.pattern);
}
this.controller.subscribe((e) => this.errors = e.results.filter((x) => x.propertyName === this.name && !x.valid));
}
blur() {
if (this.validationTrigger === "blur") {
this.validate();
}
}
input() {
if (this.validationTrigger === "change") {
this.validate();
}
}
private validate() {
this.field.setAttribute("value", this.value || "");
this.controller.validate().then((validate) => {
this.errors = validate.results.filter((x) => x.propertyName === this.name && !x.valid);
});
}
private keyDownHandler(e: KeyboardEvent) {
if (e.key === "Enter") {
this.element.dispatchEvent(DOM.createCustomEvent("enter"));
}
return true;
}
}
The problem I have is that I need (I think) to have each field subscribe to the validation callback to perform their logic to filter the errors
collection. This is because a validation can be triggered by the page that contains the submit button. But by having each field subscribe to the validation callback this also means that as soon as I validate one of the fields in the blur
or change
handlers all of the fields are validated. I only want this full form validation when you try to submit the form.
The ValidationController and the ValidationRules are created and defined in the containing page.
I feel that I have over complicated this solution and that there must be something simpler?
FluentRules
from a duplicate package
node_modules/aurelia-validation/dist/commonjs/property-info.d.ts(3,11): error TS2451: Cannot redeclare block-scoped variable 'getContextFor'.
Does aurelia-validation require that every "property" referred to in .ensure(...)
is not null? I have the following piece of code
editinfoChanged(newEditInfo: any, oldValue: any) : void {
if (this.domainobject && newEditInfo) {
this.editinfo.forEach((field: { requisiteness: string; name: string | number; label: string }) => {
if (this.isMandatory(field.requisiteness)) {
ValidationRules.ensure(this.domainobject[field.name]).displayName(field.label).required().on(this.domainobject);
};
});
}
}
which fails and produces the following error message:
Uncaught TypeError: Cannot read property 'toString' of null
at PropertyAccessorParser.parse (aurelia-validation.js?f0d7:91)
at FluentEnsure.ensure (aurelia-validation.js?f0d7:1700)
at Function.ValidationRules.ensure (aurelia-validation.js?f0d7:1767)
at eval (new-item-view.ts?c01b:112)
at Array.forEach (<anonymous>)
at NewItemView.editinfoChanged (new-item-view.ts?c01b:110)
When I look at the value of this.domainobject[field.name]
(in the first iteration) it is null and this makes me wonder if that's the cause of the error?
hello guys can someone help me with "form-field-validation" i'm trying to validate a checkbox table the validation works but the red border css not working
in the noop.bind i passe the validated list
<div class="box stackpanel vertical fit form-field-validation" noop.bind="posteUFDTOList & validate:validationController">
<div class="box-header bg-primary stackpanel horizontal fit">
<input id="chx_all" class="form-control colSelection" type="checkbox" change.delegate="cocherDecocherTout()" />
<label for="chx_all" class="box-title" i18n="sante:ui.fwm.gestionutilisateur.postes.postedetail.cocherdecocher"></label>
</div>
</div>
if (this.posteUFDTOList) {
this.validationController.validate({ object: this.posteUFDTOList });
}
Hi,
I am a newbie in aurelia.
Aurelia Validation Demo - Nested object properties
https://gist.github.com/jsobell/d81428170f1572ae916e3fbf67779014
BootstrapFormRenderer example
https://gist.github.com/y2k4life/8adacec7627d792a304f62a899f21049
I am getting correct validation when using controller.validate() method
Problem is that in BootstrapFormRenderer
In render method, elements are always empty.
render(instruction: RenderInstruction) {
debugger;
for (let { result, elements } of instruction.unrender) {
for (let element of elements) {
this.remove(element, result);
}
}
for (let { result, elements } of instruction.render) {
for (let element of elements) {
this.add(element, result);
}
}
}
Hi all! I am new to aurelia and have the following problem - I would like to use accordion in one of my pages for FAQ.
The accordion is working fine, however I would like to add show/hide function when someone is looking for a particular string and show the card with
the particular information in it.
I am doing that with jQuery, however I would like to do that with aurelia. Could you please give me some recommendation which would be the best way?
Thank you!
constructor(EventAggregator, Router, AuthService, ApplicationService, ServiceApi, ValidationControllerFactory, DialogService){
this.controller = ValidationControllerFactory.createForCurrentScope();
this.controller.addRenderer(new AureliaUXFormRenderer());
this.controllerWC = ValidationControllerFactory.createForCurrentScope();
this.controllerWC.addRenderer(new AureliaUXFormRenderer());
async attached() {
ValidationRules
.ensure('InsuredID').required()
.ensure('Date of Loss').required()
.ensure('Claim Type').required()
.ensure('AdjusterID').required()
.on(this.claim);
// this works!
this.controllerWC.ValidationRules
// ValidationRules
.ensure('InjuryType').required()
.on(this.currentItem);
// this fails
html bind fails when i use
<ux-input dense variant.bind="variant" maxlength="2" value.bind="currentItem.InjuryType & validate:controllerWC " >
</ux-input>