Last active
January 8, 2021 08:30
-
-
Save sukima/50fd0f528fe2a28f57236c89aa3bc858 to your computer and use it in GitHub Desktop.
Form validation (modifiers)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Component from '@glimmer/component'; | |
import { action } from '@ember/object'; | |
import { validate } from '../utils/validate'; | |
export default class extends Component { | |
@action | |
validatedSubmit(event) { | |
event.preventDefault(); | |
let { target: form } = event; | |
validate(...form.elements); | |
if (form.checkValidity()) { | |
this.args.onSubmit?.(new FormData(form)); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Component from '@glimmer/component'; | |
import { action } from '@ember/object'; | |
import { guidFor } from '@ember/object/internals'; | |
import { tracked } from '@glimmer/tracking'; | |
export default class extends Component { | |
fieldId = `${guidFor(this)}-field`; | |
@tracked hasValidated = false; | |
@tracked validationMessage = ''; | |
@action | |
validated({ target }) { | |
this.validationMessage = target.validationMessage; | |
this.hasValidated = true; | |
} | |
@action | |
update({ target }) { | |
this.args.onUpdate?.(target.value); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Controller from '@ember/controller'; | |
import { action } from '@ember/object'; | |
import FormData from '../utils/form-data'; | |
export default class ApplicationController extends Controller { | |
form = new FormData(); | |
@action | |
fakeSubmit(formData) { | |
alert([...formData.values()].join(', ')); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { helper } from '@ember/component/helper'; | |
export default helper(function validateCapitalized() { | |
return ({ value }) => /^[A-Z][a-z]*$/.test(value) | |
? [] | |
: ['Name must be titleized.']; | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { helper } from '@ember/component/helper'; | |
export default helper(function validateName([name]) { | |
return ({ value }) => value.toLowerCase() !== name.toLowerCase() | |
? [`Only '${name}' will work.`] | |
: []; | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { helper } from '@ember/component/helper'; | |
export default helper(function validatePhone() { | |
return ({ value }) => /\d\d\d-\d\d\d-\d\d\d\d/.test(value) | |
? [] | |
: ['Phone number must be of format xxx-xxx-xxxx.']; | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { modifier } from 'ember-modifier'; | |
import { validate } from '../utils/validate'; | |
const commaSeperate = s => s.split(',').map(i => i.trim()).filter(Boolean); | |
const reduceValidators = async (validators, ...args) => { | |
let errors = await Promise.all(validators.map(validator => validator(...args))); | |
return errors.reduce((a, b) => [...a, ...b], []); | |
} | |
export default modifier(function validity( | |
element, | |
validators, | |
{ on: eventNames = 'change,input,blur' } | |
) { | |
let autoValidationEvents = commaSeperate(eventNames); | |
let autoValidationHandler = () => validate(element); | |
let validateHandler = async () => { | |
let [error = ''] = await reduceValidators(validators, element); | |
element.checkValidity(); | |
element.setCustomValidity(error); | |
element.dispatchEvent(new CustomEvent('validated')); | |
}; | |
element.addEventListener('validate', validateHandler); | |
autoValidationEvents.forEach(eventName => { | |
element.addEventListener(eventName, autoValidationHandler); | |
}); | |
return () => { | |
element.removeEventListener('validate', validateHandler); | |
autoValidationEvents.forEach(eventName => { | |
element.removeEventListener(eventName, autoValidationHandler); | |
}); | |
}; | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data:empty::before { | |
content: '—'; | |
} | |
form > * + * { | |
margin-top: 0.5rem; | |
} | |
fieldset { | |
display: grid; | |
grid-template-columns: repeat(3, 1fr); | |
grid-gap: 1rem; | |
} | |
[data-validated] :valid { | |
box-shadow: green 0px 0px 1.5px 1px; | |
} | |
[data-validated] :invalid { | |
box-shadow: red 0px 0px 1.5px 1px; | |
} | |
:invalid + .validation-message::before { | |
content: attr(data-message); | |
color: red; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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": "2.1.1" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { tracked } from '@glimmer/tracking'; | |
export default class FormData { | |
@tracked janeName; | |
@tracked danName; | |
@tracked phoneNative; | |
@tracked phoneCustom; | |
update = new Proxy(this, { | |
get: (t, p) => Reflect.has(t, p) ? v => t[p] = v : undefined | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function validate(...elements) { | |
let validateEvent = new CustomEvent('validate'); | |
elements.forEach(el => el.dispatchEvent(validateEvent)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment