consul/ui/packages/consul-ui/app/modifiers/validate.js

140 lines
3.3 KiB
JavaScript

import Modifier from 'ember-modifier';
import { action } from '@ember/object';
class ValidationError extends Error {}
export default class ValidateModifier extends Modifier {
item = null;
hash = null;
validate(value, validations = {}) {
if(Object.keys(validations).length === 0) {
return;
}
const errors = {};
Object.entries(this.hash.validations)
// filter out strings, for now these are helps, but ain't great if someone has a item.help
.filter(([key, value]) => typeof value !== 'string')
.forEach(([key, item]) => {
// optionally set things for you
if(this.item) {
this.item[key] = value;
}
(item || []).forEach((validation) => {
const re = new RegExp(validation.test);
if(!re.test(value)) {
errors[key] = new ValidationError(validation.error);
}
});
});
const state = this.hash.chart.state;
if(state.context == null) {
state.context = {};
}
if(Object.keys(errors).length > 0) {
state.context.errors = errors;
this.hash.chart.dispatch("ERROR");
} else {
state.context.errors = null;
this.hash.chart.dispatch("RESET");
}
}
@action
reset(e) {
if(e.target.value.length === 0) {
const state = this.hash.chart.state;
if(!state.context) {
state.context = {};
}
if(!state.context.errors) {
state.context.errors = {};
}
Object.entries(this.hash.validations)
// filter out strings, for now these are helps, but ain't great if someone has a item.help
.filter(([key, value]) => typeof value !== 'string')
.forEach(([key, item]) => {
if(typeof state.context.errors[key] !== 'undefined') {
delete state.context.errors[key];
}
});
if(Object.keys(state.context.errors).length === 0) {
state.context.errors = null;
this.hash.chart.dispatch("RESET");
}
}
}
async connect([value], _hash) {
this.element.addEventListener(
'input',
this.listen
);
this.element.addEventListener(
'blur',
this.reset
);
if(this.element.value.length > 0) {
await Promise.resolve();
if(this && this.element) {
this.validate(this.element.value, this.hash.validations);
}
}
}
@action
listen(e) {
this.validate(e.target.value, this.hash.validations);
}
disconnect() {
this.item = null;
this.hash = null;
this.element.removeEventListener(
'input',
this.listen
)
this.element.removeEventListener(
'blur',
this.reset
)
}
didReceiveArguments() {
const [value] = this.args.positional;
const _hash = this.args.named;
this.item = value;
this.hash = _hash;
if(typeof _hash.chart === 'undefined') {
this.hash.chart = {
state: {
context: {}
},
dispatch: (state) => {
switch(state) {
case 'ERROR':
_hash.onchange(this.hash.chart.state.context.errors);
break;
case 'RESET':
_hash.onchange();
break;
}
}
};
}
}
didInstall() {
this.connect(this.args.positional, this.args.named);
}
willRemove() {
this.disconnect();
}
}