Skip to content

Instantly share code, notes, and snippets.

@freshcutdevelopment
Last active August 30, 2017 20:14
Show Gist options
  • Save freshcutdevelopment/170c2386f243e7095e276811dab52299 to your computer and use it in GitHub Desktop.
Save freshcutdevelopment/170c2386f243e7095e276811dab52299 to your computer and use it in GitHub Desktop.
Adding validation to the aurelia-app-contacts sample
import {
ValidationRenderer,
RenderInstruction,
ValidateResult
} from 'aurelia-validation';
export class BootstrapFormRenderer {
render(instruction: RenderInstruction) {
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);
}
}
}
add(element: Element, result: ValidateResult) {
if (result.valid) {
return;
}
const formGroup = element.closest('.form-group');
if (!formGroup) {
return;
}
// add the has-error class to the enclosing form-group div
formGroup.classList.add('has-error');
// add help-block
const message = document.createElement('span');
message.className = 'help-block validation-message';
message.textContent = result.message;
message.id = `validation-message-${result.id}`;
formGroup.appendChild(message);
}
remove(element: Element, result: ValidateResult) {
if (result.valid) {
return;
}
const formGroup = element.closest('.form-group');
if (!formGroup) {
return;
}
// remove help-block
const message = formGroup.querySelector(`#validation-message-${result.id}`);
if (message) {
formGroup.removeChild(message);
// remove the has-error class from the enclosing form-group div
if (formGroup.querySelectorAll('.help-block.validation-message').length === 0) {
formGroup.classList.remove('has-error');
}
}
}
}
<template>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Profile</h3>
</div>
<div class="panel-body">
<form role="form" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">First Name</label>
<div class="col-sm-10">
<input type="text" placeholder="first name" class="form-control" value.bind="contact.firstName">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Last Name</label>
<div class="col-sm-10">
<input type="text" placeholder="last name" class="form-control" value.bind="contact.lastName">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="text" placeholder="email" class="form-control" value.bind="contact.email & validate">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Phone Number</label>
<div class="col-sm-10">
<input type="text" placeholder="phone number" class="form-control" value.bind="contact.phoneNumber">
</div>
</div>
</form>
</div>
</div>
<div class="button-bar">
<button class="btn btn-success" click.delegate="save()" disabled.bind="!canSave">Save</button>
</div>
</template>
import {EventAggregator} from 'aurelia-event-aggregator';
import {WebAPI} from './web-api';
import {ContactUpdated,ContactViewed} from './messages';
import {areEqual} from './utility';
import {NewInstance} from 'aurelia-framework';
import {ValidationRules, ValidationController} from 'aurelia-validation';
import {BootstrapFormRenderer} from './bootstrap-form-renderer';
export class ContactDetail {
static inject = [WebAPI, EventAggregator, NewInstance.of(ValidationController)];
constructor(api, ea, controller){
this.api = api;
this.ea = ea;
this.controller = controller;
this.controller.addRenderer(new BootstrapFormRenderer());
}
activate(params, routeConfig){
this.routeConfig = routeConfig;
return this.api.getContactDetails(params.id).then(contact => {
this.contact = Object.assign(new Contact(), contact);;
this.routeConfig.navModel.setTitle(contact.firstName);
this.originalContact = JSON.parse(JSON.stringify(contact));
this.ea.publish(new ContactViewed(contact));
});
}
get canSave(){
return this.contact.firstName && this.contact.lastName && !this.api.isRequesting;
}
save(){
this.api.saveContact(this.contact).then(contact => {
this.contact = contact;
this.routeConfig.navModel.setTitle(contact.firstName);
this.originalContact = JSON.parse(JSON.stringify(contact));
this.ea.publish(new ContactUpdated(this.contact));
});
}
canDeactivate(){
if(!areEqual(this.originalContact, this.contact)){
let result = confirm('You have unsaved changes. Are you sure you wish to leave?');
if(!result){
this.ea.publish(new ContactViewed(this.contact));
}
return result;
}
return true;
}
deactivate(){
this.controller.reset();
}
}
export class Contact {
email= '';
}
ValidationRules
.ensure(a => a.email).required().email()
.on(Contact);
import 'bootstrap';
import environment from './environment';
//Configure Bluebird Promises.
//Note: You may want to use environment-specific configuration.
Promise.config({
warnings: {
wForgottenReturn: false
}
});
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.plugin('aurelia-validation')
.feature('resources');
if (environment.debug) {
aurelia.use.developmentLogging();
}
if (environment.testing) {
aurelia.use.plugin('aurelia-testing');
}
aurelia.start().then(() => aurelia.setRoot());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment