Skip to content

Instantly share code, notes, and snippets.

@stalniy
Created August 21, 2018 10:05
Show Gist options
  • Save stalniy/530c6296bffc0113e5a1371c052da1b0 to your computer and use it in GitHub Desktop.
Save stalniy/530c6296bffc0113e5a1371c052da1b0 to your computer and use it in GitHub Desktop.
Vue HTML5 form validation
const props = {
value: { required: true },
tag: { type: String, default: 'div' },
};
const STATIC_PROPS = { ...props };
const VALIDATORS = {};
export default {
props,
data() {
return {
isValid: true,
};
},
watch: {
value: 'updateValidityLater',
rulesProps: 'updateValidityLater',
},
computed: {
rules() {
return Object.keys(this.$options.propsData)
.reduce((rules, key) => (STATIC_PROPS[key] ? rules : rules.concat(key)), []);
},
rulesProps() {
return this.rules.map(rule => this[rule]);
},
},
methods: {
invalidate(event) {
event.preventDefault();
this.updateValidity();
},
updateValidity() {
const { validity } = this.$refs.input;
this.isValid = validity.valid;
if (validity.customError || validity.valid) {
this.isValid = this.validate();
}
},
updateValidityLater() {
this.$nextTick(this.updateValidity);
},
validate() {
const failedRule = this.rules
.find(rule => !VALIDATORS[rule](this[rule], this.value, this));
this.$refs.input.setCustomValidity(failedRule || '');
return !failedRule;
},
},
render(h) {
let children = this.$scopedSlots.default({ isValid: this.isValid });
if (!Array.isArray(children)) {
children = [children];
}
return h(this.tag, [
...children,
h('input', {
attrs: this.$attrs,
style: { display: 'none' },
ref: 'input',
domProps: {
value: this.value,
},
on: {
invalid: this.invalidate,
},
}),
]);
},
registerValidator(name, defs, fn) {
props[name] = defs || {};
VALIDATORS[name] = fn;
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment