Skip to content

Instantly share code, notes, and snippets.

@hakilebara
Last active November 7, 2021 23:36
Show Gist options
  • Save hakilebara/e959b416886f69472a96cc8c19dc9157 to your computer and use it in GitHub Desktop.
Save hakilebara/e959b416886f69472a96cc8c19dc9157 to your computer and use it in GitHub Desktop.
validation modifer - running validations
import Controller from '@ember/controller';
import { action } from '@ember/object';
import { isBlank } from '@ember/utils';
export default class ApplicationController extends Controller {
@action
handleValidated({ target: { validationMessage, name } }) {
console.log('did-validate event caught by form');
console.table([{
"input name": name,
value: arguments[0].target.value,
isValid: isBlank(validationMessage),
"validation error message": validationMessage
}]);
}
@action
validatePresence({ value }) {
if(isBlank(value)) {
return "input cannot be empty";
}
}
@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";
}
}
}
import { modifier } from 'ember-modifier';
import { assert } from '@ember/debug';
// transforms a coma separated string of events into an array
// 'blur ,input,, change' becomes ['blur', 'input', 'change']
function parseEventsList(string) {
return string
.split(',')
.map(i => i.trim())
.filter(Boolean);
}
async function runValidators(validators, input) {
// returns a single Promise that resolves to an array of the results
// of the input validators (validation functions)
let errors = await Promise.all(validators.map(validator => validator(input)));
return errors.filter(Boolean);
}
function addEventListeners(input, eventsToValidateOn, validators) {
async function runValidation() {
// destructure the first error message of the array
// or set error to ''
let foo = await runValidators(validators, input);
let [error = ''] = foo;
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);
});
}
// When the modifier is destroyed,
// clean up the changes that the modifier made in the first place
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;
}
h2 {
border: dotted red;
padding: 8px;
text-align: center;
}
<h1>Ember Form Validation API Demo - Running validations</h1>
<h2> open your console and try to fill in the form </h2>
<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.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": true
},
"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