Skip to content

Instantly share code, notes, and snippets.

@hakilebara
Last active November 3, 2021 11:38
Show Gist options
  • Save hakilebara/ea69395b34cc2309c164546777ab4f76 to your computer and use it in GitHub Desktop.
Save hakilebara/ea69395b34cc2309c164546777ab4f76 to your computer and use it in GitHub Desktop.
validation modifier - display validations
import Controller from '@ember/controller';
import { action } from '@ember/object';
import { isEmpty } from '@ember/utils';
import { tracked } from '@glimmer/tracking';
class Validation {
@tracked message = '';
@tracked displayError = false;
get displayMessage() {
if (this.displayError) {
return this.message;
}
}
}
function buildValidations(validationArray) {
return validationArray.reduce((acc, value) => {
acc[value] = new Validation();
return acc;
}, {});
}
export default class ApplicationController extends Controller {
validations = buildValidations(['firstname', 'email']);
@action
handleValidated({ target: { validationMessage, name } }) {
this.validations[name].message = validationMessage;
}
@action
validatePresence({ value }) {
if(isEmpty(value)) {
return ["input cannot be empty"];
}
else {
return [];
}
}
@action
validateEmail({ value }) {
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if(!re.test(String(value))) {
return ["email is not valid"];
}
else {
return [];
}
}
}
import { modifier } from 'ember-modifier';
import { assert } from '@ember/debug';
function parseEventsList(string) {
return string
.split(',')
.map(i => i.trim())
.filter(Boolean);
}
async function runValidators(validators, ...args) {
let errors = await Promise.all(validators.map(validator => validator(...args)));
return errors.flat();
}
function addEventListeners(input, eventsToValidateOn, validators) {
async function runValidation() {
let [error = ''] = await runValidators(validators, input);
input.checkValidity();
input.setCustomValidity(error);
input.dispatchEvent(new CustomEvent('did-validate', { bubbles: true }));
}
eventsToValidateOn.forEach(eventName => {
input.addEventListener(eventName, runValidation);
});
return { runValidation };
}
function validation(
input,
validators,
{ on: eventNames = 'change,input,blur' }
) {
let eventsToValidateOn = parseEventsList(eventNames);
let { runValidation } = addEventListeners(
input,
eventsToValidateOn,
validators
);
function cleanupEventListeners() {
eventsToValidateOn.forEach(eventName => {
input.removeEventListener(eventName, runValidation);
});
}
return cleanupEventListeners;
}
export default modifier(validation);
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
form {
display: flex;
flex-direction: column;
}
label {
margin-bottom: 4px;
margin-top: 24px;
}
input {
height: 30px;
}
.error {
color: red;
}
<h1>Ember Form Validation API Demo</h1>
<form
{{on 'did-validate' this.handleValidated}}
novalidate
>
<label for="firstname-input">
Enter your first name
</label>
<input
id="firstname-input"
name="firstname"
autocomplete="off"
{{validation this.validatePresence}}/>
<span class="error">{{this.validations.firstname.message}}</span>
<label for="email-input">
Enter your email address
</label>
<input
id="email-input"
name="email"
autocomplete="off"
{{validation this.validatePresence this.validateEmail}}/>
<span class="error">{{this.validations.email.message}}</span>
</form>
{
"version": "0.17.2",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": true,
"_APPLICATION_TEMPLATE_WRAPPER": false,
"_JQUERY_INTEGRATION": false
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js",
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1"
},
"addons": {
"@glimmer/component": "1.0.0",
"ember-modifier": "3.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment