Adds default validation messages for all rule types
This commit is contained in:
parent
e952e46aad
commit
ba24fc21e8
574
dist/formulate.esm.js
vendored
574
dist/formulate.esm.js
vendored
@ -161,6 +161,17 @@ function arrayify (item) {
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* How to add an item.
|
||||
* @param {string} item
|
||||
*/
|
||||
function sentence (item) {
|
||||
if (typeof item === 'string') {
|
||||
return item[0].toUpperCase() + item.substr(1)
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array or string return an array of callables.
|
||||
* @param {array|string} validation
|
||||
@ -187,6 +198,7 @@ function parseRule (rule, rules) {
|
||||
return [rule, []]
|
||||
}
|
||||
if (Array.isArray(rule) && rule.length) {
|
||||
rule = rule.map(function (r) { return r; }); // light clone
|
||||
if (typeof rule[0] === 'string' && rules.hasOwnProperty(rule[0])) {
|
||||
return [rules[rule.shift()], rule]
|
||||
}
|
||||
@ -217,88 +229,6 @@ var rules = {
|
||||
return Promise.resolve(['yes', 'on', '1', 1, true, 'true'].includes(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: must be a value
|
||||
*/
|
||||
required: function (value, isRequired) {
|
||||
if ( isRequired === void 0 ) isRequired = true;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (!isRequired || ['no', 'false'].includes(isRequired)) {
|
||||
return true
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return !!value.length
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return !!value
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return (!value) ? false : !!Object.keys(value).length
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is in an array (stack).
|
||||
*/
|
||||
in: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) !== undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is not in stack.
|
||||
*/
|
||||
not: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) === undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Match the value against a (stack) of patterns or strings
|
||||
*/
|
||||
matches: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(!!stack.find(function (pattern) {
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(value)
|
||||
}
|
||||
return pattern === value
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a string is a valid url
|
||||
*/
|
||||
url: function (value) {
|
||||
return Promise.resolve(isUrl(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
@ -310,6 +240,34 @@ var rules = {
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue > timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha
|
||||
*/
|
||||
alpha: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z]+$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z0-9]+$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
@ -321,45 +279,13 @@ var rules = {
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue < timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
alpha: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-z][A-Z]$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
number: function (value) {
|
||||
return Promise.resolve(!isNaN(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z0-9]$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is between two other values
|
||||
*/
|
||||
between: function (value, from, to) {
|
||||
if ( from === void 0 ) from = 0;
|
||||
if ( to === void 0 ) to = 10;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (from === null || to === null || isNaN(from) || isNaN(to)) {
|
||||
return false
|
||||
@ -377,6 +303,13 @@ var rules = {
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: tests
|
||||
*/
|
||||
@ -386,6 +319,58 @@ var rules = {
|
||||
return Promise.resolve(isEmail.test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is in an array (stack).
|
||||
*/
|
||||
in: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) !== undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Match the value against a (stack) of patterns or strings
|
||||
*/
|
||||
matches: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(!!stack.find(function (pattern) {
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(value)
|
||||
}
|
||||
return pattern === value
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the maximum value of a particular.
|
||||
*/
|
||||
max: function (value, minimum) {
|
||||
if ( minimum === void 0 ) minimum = 10;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
minimum = Number(minimum);
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value);
|
||||
return value <= minimum
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length <= minimum
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length <= minimum
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the file type is correct.
|
||||
*/
|
||||
@ -409,6 +394,8 @@ var rules = {
|
||||
* Check the minimum value of a particular.
|
||||
*/
|
||||
min: function (value, minimum) {
|
||||
if ( minimum === void 0 ) minimum = 1;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
minimum = Number(minimum);
|
||||
if (!isNaN(value)) {
|
||||
@ -426,23 +413,243 @@ var rules = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the minimum value of a particular.
|
||||
* Rule: Value is not in stack.
|
||||
*/
|
||||
max: function (value, minimum) {
|
||||
return Promise.resolve((function () {
|
||||
minimum = Number(minimum);
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value);
|
||||
return value <= minimum
|
||||
not: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length <= minimum
|
||||
return item === value
|
||||
}) === undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
number: function (value) {
|
||||
return Promise.resolve(!isNaN(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: must be a value
|
||||
*/
|
||||
required: function (value, isRequired) {
|
||||
if ( isRequired === void 0 ) isRequired = true;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (!isRequired || ['no', 'false'].includes(isRequired)) {
|
||||
return true
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length <= minimum
|
||||
return !!value.length
|
||||
}
|
||||
return false
|
||||
if (typeof value === 'string') {
|
||||
return !!value
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return (!value) ? false : !!Object.keys(value).length
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a string is a valid url
|
||||
*/
|
||||
url: function (value) {
|
||||
return Promise.resolve(isUrl(value))
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validation error message generators.
|
||||
*/
|
||||
var en = {
|
||||
|
||||
/**
|
||||
* Valid accepted value.
|
||||
*/
|
||||
accepted: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ("Please accept the " + name + ".")
|
||||
},
|
||||
|
||||
/**
|
||||
* The date is not after.
|
||||
*/
|
||||
after: function (ref) {
|
||||
var name = ref.name;
|
||||
var args = ref.args;
|
||||
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return ((sentence(name)) + " must be after " + (args[0]) + ".")
|
||||
}
|
||||
return ((sentence(name)) + " must be a later date.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The value is not a letter.
|
||||
*/
|
||||
alpha: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " can only contain alphabetical characters.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " can only contain letters and numbers.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The date is not before.
|
||||
*/
|
||||
before: function (ref) {
|
||||
var name = ref.name;
|
||||
var args = ref.args;
|
||||
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return ((sentence(name)) + " must be before " + (args[0]) + ".")
|
||||
}
|
||||
return ((sentence(name)) + " must be an earlier date.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The value is not between two numbers or lengths
|
||||
*/
|
||||
between: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
var args = ref.args;
|
||||
|
||||
if (!isNaN(value)) {
|
||||
return ((sentence(name)) + " must be between " + (args[0]) + " and " + (args[1]) + ".")
|
||||
}
|
||||
return ((sentence(name)) + " must be between " + (args[0]) + " and " + (args[1]) + " characters long.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Is not a valid date.
|
||||
*/
|
||||
date: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " is not a valid date.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render method for error messages.
|
||||
*/
|
||||
default: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return "This field isn’t valid."
|
||||
},
|
||||
|
||||
/**
|
||||
* Is not a valid email address.
|
||||
*/
|
||||
email: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
return (value + " is not a valid email address.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is an allowed value.
|
||||
*/
|
||||
in: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
return ("“" + (sentence(value)) + "” is not an allowed " + name + ".")
|
||||
}
|
||||
return ((sentence(name)) + " is not an allowed value.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is not a match.
|
||||
*/
|
||||
matches: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " is not an allowed value.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The maximum value allowed.
|
||||
*/
|
||||
max: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
var args = ref.args;
|
||||
|
||||
if (!isNaN(value)) {
|
||||
return (name + " must be less than " + (args[0]) + ".")
|
||||
}
|
||||
return (name + " must be less than " + (args[0]) + " characters long.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The maximum value allowed.
|
||||
*/
|
||||
min: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
var args = ref.args;
|
||||
|
||||
if (!isNaN(value)) {
|
||||
return (name + " must be more than " + (args[0]) + ".")
|
||||
}
|
||||
return (name + " must be more than " + (args[0]) + " characters long.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The field is not an allowed value
|
||||
*/
|
||||
not: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
return ("“" + value + "” is not an allowed " + name + ".")
|
||||
},
|
||||
|
||||
/**
|
||||
* The field is not a number
|
||||
*/
|
||||
number: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " must be a number.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Required field.
|
||||
*/
|
||||
required: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " is required.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is not a url.
|
||||
*/
|
||||
url: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return "Please include a valid url."
|
||||
}
|
||||
};
|
||||
|
||||
@ -453,9 +660,6 @@ var rules = {
|
||||
*/
|
||||
var context = {
|
||||
context: function context () {
|
||||
if (this.debug) {
|
||||
console.log(((this.type) + " re-context"));
|
||||
}
|
||||
return defineModel.call(this, Object.assign({}, {type: this.type,
|
||||
value: this.value,
|
||||
name: this.nameOrFallback,
|
||||
@ -464,7 +668,8 @@ var context = {
|
||||
id: this.id || this.defaultId,
|
||||
label: this.label,
|
||||
labelPosition: this.logicalLabelPosition,
|
||||
attributes: this.elementAttributes},
|
||||
attributes: this.elementAttributes,
|
||||
blurHandler: blurHandler.bind(this)},
|
||||
this.typeContext))
|
||||
},
|
||||
nameOrFallback: nameOrFallback,
|
||||
@ -473,7 +678,9 @@ var context = {
|
||||
logicalLabelPosition: logicalLabelPosition,
|
||||
isVmodeled: isVmodeled,
|
||||
mergedErrors: mergedErrors,
|
||||
hasErrors: hasErrors
|
||||
hasErrors: hasErrors,
|
||||
showFieldErrors: showFieldErrors,
|
||||
mergedValidationName: mergedValidationName
|
||||
};
|
||||
|
||||
/**
|
||||
@ -533,6 +740,33 @@ function logicalLabelPosition () {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The validation label to use.
|
||||
*/
|
||||
function mergedValidationName () {
|
||||
if (this.validationName) {
|
||||
return this.validationName
|
||||
}
|
||||
if (typeof this.name === 'string') {
|
||||
return this.name
|
||||
}
|
||||
if (this.label) {
|
||||
return this.label
|
||||
}
|
||||
return this.type
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the field should show it's error (if it has one)
|
||||
* @return {boolean}
|
||||
*/
|
||||
function showFieldErrors () {
|
||||
if (this.showErrors) {
|
||||
return this.showErrors
|
||||
}
|
||||
return this.behavioralErrorVisibility
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the element’s name, or select a fallback.
|
||||
*/
|
||||
@ -593,6 +827,15 @@ function hasErrors () {
|
||||
return !!this.mergedErrors.length
|
||||
}
|
||||
|
||||
/**
|
||||
* Bound into the context object.
|
||||
*/
|
||||
function blurHandler () {
|
||||
if (this.errorBehavior === 'blur') {
|
||||
this.behavioralErrorVisibility = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
@ -636,7 +879,8 @@ var script = {
|
||||
inheritAttrs: false,
|
||||
inject: {
|
||||
formulateFormSetter: { default: undefined },
|
||||
formulateFormRegister: { default: undefined }
|
||||
formulateFormRegister: { default: undefined },
|
||||
getFormValues: { default: function () { return function () { return ({}); }; } }
|
||||
},
|
||||
model: {
|
||||
prop: 'formulateValue',
|
||||
@ -695,15 +939,23 @@ var script = {
|
||||
type: [String, Boolean, Array],
|
||||
default: false
|
||||
},
|
||||
validationBehavior: {
|
||||
validationName: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
errorBehavior: {
|
||||
type: String,
|
||||
default: 'blur',
|
||||
validator: function (value) {
|
||||
return ['blur', 'live'].includes(value)
|
||||
}
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
showErrors: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
@ -712,6 +964,7 @@ var script = {
|
||||
defaultId: nanoid(9),
|
||||
localAttributes: {},
|
||||
internalModelProxy: this.formulateValue,
|
||||
behavioralErrorVisibility: (this.errorBehavior === 'live'),
|
||||
validationErrors: []
|
||||
}
|
||||
},
|
||||
@ -765,7 +1018,13 @@ var script = {
|
||||
var args = ref[1];
|
||||
|
||||
return rule.apply(void 0, [ this$1.context.model ].concat( args ))
|
||||
.then(function (res) { return res ? false : 'Validation error!'; })
|
||||
.then(function (res) { return res ? false : this$1.$formulate.validationMessage(rule.name, {
|
||||
args: args,
|
||||
name: this$1.mergedValidationName,
|
||||
value: this$1.context.model,
|
||||
vm: this$1,
|
||||
formValues: this$1.getFormValues()
|
||||
}); })
|
||||
})
|
||||
)
|
||||
.then(function (result) { return result.filter(function (result) { return result; }); })
|
||||
@ -864,6 +1123,7 @@ var __vue_render__ = function() {
|
||||
attrs: {
|
||||
"data-classification": _vm.classification,
|
||||
"data-has-errors": _vm.hasErrors,
|
||||
"data-is-showing-errors": _vm.hasErrors && _vm.showFieldErrors,
|
||||
"data-type": _vm.type
|
||||
}
|
||||
},
|
||||
@ -926,7 +1186,9 @@ var __vue_render__ = function() {
|
||||
})
|
||||
: _vm._e(),
|
||||
_vm._v(" "),
|
||||
_c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } })
|
||||
_vm.showFieldErrors
|
||||
? _c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } })
|
||||
: _vm._e()
|
||||
],
|
||||
1
|
||||
)
|
||||
@ -969,7 +1231,8 @@ var script$1 = {
|
||||
provide: function provide () {
|
||||
return {
|
||||
formulateFormSetter: this.setFieldValue,
|
||||
formulateFormRegister: this.register
|
||||
formulateFormRegister: this.register,
|
||||
getFormValues: this.getFormValues
|
||||
}
|
||||
},
|
||||
name: 'FormulateForm',
|
||||
@ -1051,6 +1314,9 @@ var script$1 = {
|
||||
formSubmitted: function formSubmitted () {
|
||||
// perform validation here
|
||||
this.$emit('submit', this.formModel);
|
||||
},
|
||||
getFormValues: function getFormValues () {
|
||||
return this.internalFormModelProxy
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1379,6 +1645,7 @@ var __vue_render__$4 = function() {
|
||||
: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$a = _vm.context.model,
|
||||
$$el = $event.target,
|
||||
@ -1427,6 +1694,7 @@ var __vue_render__$4 = function() {
|
||||
checked: _vm._q(_vm.context.model, _vm.context.value)
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
return _vm.$set(_vm.context, "model", _vm.context.value)
|
||||
}
|
||||
@ -1455,6 +1723,7 @@ var __vue_render__$4 = function() {
|
||||
value: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
@ -1549,6 +1818,7 @@ var __vue_render__$5 = function() {
|
||||
: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$a = _vm.context.model,
|
||||
$$el = $event.target,
|
||||
@ -1594,6 +1864,7 @@ var __vue_render__$5 = function() {
|
||||
attrs: { type: "radio" },
|
||||
domProps: { checked: _vm._q(_vm.context.model, null) },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
return _vm.$set(_vm.context, "model", null)
|
||||
}
|
||||
@ -1619,6 +1890,7 @@ var __vue_render__$5 = function() {
|
||||
attrs: { type: _vm.type },
|
||||
domProps: { value: _vm.context.model },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
@ -1711,6 +1983,7 @@ var __vue_render__$6 = function() {
|
||||
],
|
||||
attrs: { "data-placeholder-selected": _vm.placeholderSelected },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$selectedVal = Array.prototype.filter
|
||||
.call($event.target.options, function(o) {
|
||||
@ -1863,6 +2136,7 @@ var __vue_render__$7 = function() {
|
||||
],
|
||||
domProps: { value: _vm.context.model },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
@ -1927,7 +2201,11 @@ var Formulate = function Formulate () {
|
||||
FormulateInputTextArea: FormulateInputTextArea
|
||||
},
|
||||
library: library,
|
||||
rules: rules
|
||||
rules: rules,
|
||||
locale: 'en',
|
||||
locales: {
|
||||
en: en
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -1997,6 +2275,20 @@ Formulate.prototype.rules = function rules () {
|
||||
return this.options.rules
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the validation message for a particular error.
|
||||
*/
|
||||
Formulate.prototype.validationMessage = function validationMessage (rule, validationContext) {
|
||||
var generators = this.options.locales[this.options.locale];
|
||||
if (generators.hasOwnProperty(rule)) {
|
||||
return generators[rule](validationContext)
|
||||
}
|
||||
if (generators.hasOwnProperty('default')) {
|
||||
return generators.default(validationContext)
|
||||
}
|
||||
return 'This field does not have a valid value'
|
||||
};
|
||||
|
||||
var Formulate$1 = new Formulate();
|
||||
|
||||
export default Formulate$1;
|
||||
|
574
dist/formulate.min.js
vendored
574
dist/formulate.min.js
vendored
@ -164,6 +164,17 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* How to add an item.
|
||||
* @param {string} item
|
||||
*/
|
||||
function sentence (item) {
|
||||
if (typeof item === 'string') {
|
||||
return item[0].toUpperCase() + item.substr(1)
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array or string return an array of callables.
|
||||
* @param {array|string} validation
|
||||
@ -190,6 +201,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return [rule, []]
|
||||
}
|
||||
if (Array.isArray(rule) && rule.length) {
|
||||
rule = rule.map(function (r) { return r; }); // light clone
|
||||
if (typeof rule[0] === 'string' && rules.hasOwnProperty(rule[0])) {
|
||||
return [rules[rule.shift()], rule]
|
||||
}
|
||||
@ -220,88 +232,6 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return Promise.resolve(['yes', 'on', '1', 1, true, 'true'].includes(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: must be a value
|
||||
*/
|
||||
required: function (value, isRequired) {
|
||||
if ( isRequired === void 0 ) isRequired = true;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (!isRequired || ['no', 'false'].includes(isRequired)) {
|
||||
return true
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return !!value.length
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return !!value
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return (!value) ? false : !!Object.keys(value).length
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is in an array (stack).
|
||||
*/
|
||||
in: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) !== undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is not in stack.
|
||||
*/
|
||||
not: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) === undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Match the value against a (stack) of patterns or strings
|
||||
*/
|
||||
matches: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(!!stack.find(function (pattern) {
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(value)
|
||||
}
|
||||
return pattern === value
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a string is a valid url
|
||||
*/
|
||||
url: function (value) {
|
||||
return Promise.resolve(isUrl(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
@ -313,6 +243,34 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue > timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha
|
||||
*/
|
||||
alpha: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z]+$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z0-9]+$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
@ -324,45 +282,13 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue < timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
alpha: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-z][A-Z]$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
number: function (value) {
|
||||
return Promise.resolve(!isNaN(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z0-9]$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is between two other values
|
||||
*/
|
||||
between: function (value, from, to) {
|
||||
if ( from === void 0 ) from = 0;
|
||||
if ( to === void 0 ) to = 10;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (from === null || to === null || isNaN(from) || isNaN(to)) {
|
||||
return false
|
||||
@ -380,6 +306,13 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: tests
|
||||
*/
|
||||
@ -389,6 +322,58 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return Promise.resolve(isEmail.test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is in an array (stack).
|
||||
*/
|
||||
in: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) !== undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Match the value against a (stack) of patterns or strings
|
||||
*/
|
||||
matches: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(!!stack.find(function (pattern) {
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(value)
|
||||
}
|
||||
return pattern === value
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the maximum value of a particular.
|
||||
*/
|
||||
max: function (value, minimum) {
|
||||
if ( minimum === void 0 ) minimum = 10;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
minimum = Number(minimum);
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value);
|
||||
return value <= minimum
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length <= minimum
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length <= minimum
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the file type is correct.
|
||||
*/
|
||||
@ -412,6 +397,8 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
* Check the minimum value of a particular.
|
||||
*/
|
||||
min: function (value, minimum) {
|
||||
if ( minimum === void 0 ) minimum = 1;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
minimum = Number(minimum);
|
||||
if (!isNaN(value)) {
|
||||
@ -429,23 +416,243 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the minimum value of a particular.
|
||||
* Rule: Value is not in stack.
|
||||
*/
|
||||
max: function (value, minimum) {
|
||||
return Promise.resolve((function () {
|
||||
minimum = Number(minimum);
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value);
|
||||
return value <= minimum
|
||||
not: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length <= minimum
|
||||
return item === value
|
||||
}) === undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
number: function (value) {
|
||||
return Promise.resolve(!isNaN(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: must be a value
|
||||
*/
|
||||
required: function (value, isRequired) {
|
||||
if ( isRequired === void 0 ) isRequired = true;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (!isRequired || ['no', 'false'].includes(isRequired)) {
|
||||
return true
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length <= minimum
|
||||
return !!value.length
|
||||
}
|
||||
return false
|
||||
if (typeof value === 'string') {
|
||||
return !!value
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return (!value) ? false : !!Object.keys(value).length
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a string is a valid url
|
||||
*/
|
||||
url: function (value) {
|
||||
return Promise.resolve(isUrl(value))
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validation error message generators.
|
||||
*/
|
||||
var en = {
|
||||
|
||||
/**
|
||||
* Valid accepted value.
|
||||
*/
|
||||
accepted: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ("Please accept the " + name + ".")
|
||||
},
|
||||
|
||||
/**
|
||||
* The date is not after.
|
||||
*/
|
||||
after: function (ref) {
|
||||
var name = ref.name;
|
||||
var args = ref.args;
|
||||
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return ((sentence(name)) + " must be after " + (args[0]) + ".")
|
||||
}
|
||||
return ((sentence(name)) + " must be a later date.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The value is not a letter.
|
||||
*/
|
||||
alpha: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " can only contain alphabetical characters.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " can only contain letters and numbers.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The date is not before.
|
||||
*/
|
||||
before: function (ref) {
|
||||
var name = ref.name;
|
||||
var args = ref.args;
|
||||
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return ((sentence(name)) + " must be before " + (args[0]) + ".")
|
||||
}
|
||||
return ((sentence(name)) + " must be an earlier date.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The value is not between two numbers or lengths
|
||||
*/
|
||||
between: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
var args = ref.args;
|
||||
|
||||
if (!isNaN(value)) {
|
||||
return ((sentence(name)) + " must be between " + (args[0]) + " and " + (args[1]) + ".")
|
||||
}
|
||||
return ((sentence(name)) + " must be between " + (args[0]) + " and " + (args[1]) + " characters long.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Is not a valid date.
|
||||
*/
|
||||
date: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " is not a valid date.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render method for error messages.
|
||||
*/
|
||||
default: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return "This field isn’t valid."
|
||||
},
|
||||
|
||||
/**
|
||||
* Is not a valid email address.
|
||||
*/
|
||||
email: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
return (value + " is not a valid email address.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is an allowed value.
|
||||
*/
|
||||
in: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
return ("“" + (sentence(value)) + "” is not an allowed " + name + ".")
|
||||
}
|
||||
return ((sentence(name)) + " is not an allowed value.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is not a match.
|
||||
*/
|
||||
matches: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " is not an allowed value.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The maximum value allowed.
|
||||
*/
|
||||
max: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
var args = ref.args;
|
||||
|
||||
if (!isNaN(value)) {
|
||||
return (name + " must be less than " + (args[0]) + ".")
|
||||
}
|
||||
return (name + " must be less than " + (args[0]) + " characters long.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The maximum value allowed.
|
||||
*/
|
||||
min: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
var args = ref.args;
|
||||
|
||||
if (!isNaN(value)) {
|
||||
return (name + " must be more than " + (args[0]) + ".")
|
||||
}
|
||||
return (name + " must be more than " + (args[0]) + " characters long.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The field is not an allowed value
|
||||
*/
|
||||
not: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
return ("“" + value + "” is not an allowed " + name + ".")
|
||||
},
|
||||
|
||||
/**
|
||||
* The field is not a number
|
||||
*/
|
||||
number: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " must be a number.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Required field.
|
||||
*/
|
||||
required: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " is required.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is not a url.
|
||||
*/
|
||||
url: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return "Please include a valid url."
|
||||
}
|
||||
};
|
||||
|
||||
@ -456,9 +663,6 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
*/
|
||||
var context = {
|
||||
context: function context () {
|
||||
if (this.debug) {
|
||||
console.log(((this.type) + " re-context"));
|
||||
}
|
||||
return defineModel.call(this, Object.assign({}, {type: this.type,
|
||||
value: this.value,
|
||||
name: this.nameOrFallback,
|
||||
@ -467,7 +671,8 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
id: this.id || this.defaultId,
|
||||
label: this.label,
|
||||
labelPosition: this.logicalLabelPosition,
|
||||
attributes: this.elementAttributes},
|
||||
attributes: this.elementAttributes,
|
||||
blurHandler: blurHandler.bind(this)},
|
||||
this.typeContext))
|
||||
},
|
||||
nameOrFallback: nameOrFallback,
|
||||
@ -476,7 +681,9 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
logicalLabelPosition: logicalLabelPosition,
|
||||
isVmodeled: isVmodeled,
|
||||
mergedErrors: mergedErrors,
|
||||
hasErrors: hasErrors
|
||||
hasErrors: hasErrors,
|
||||
showFieldErrors: showFieldErrors,
|
||||
mergedValidationName: mergedValidationName
|
||||
};
|
||||
|
||||
/**
|
||||
@ -536,6 +743,33 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The validation label to use.
|
||||
*/
|
||||
function mergedValidationName () {
|
||||
if (this.validationName) {
|
||||
return this.validationName
|
||||
}
|
||||
if (typeof this.name === 'string') {
|
||||
return this.name
|
||||
}
|
||||
if (this.label) {
|
||||
return this.label
|
||||
}
|
||||
return this.type
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the field should show it's error (if it has one)
|
||||
* @return {boolean}
|
||||
*/
|
||||
function showFieldErrors () {
|
||||
if (this.showErrors) {
|
||||
return this.showErrors
|
||||
}
|
||||
return this.behavioralErrorVisibility
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the element’s name, or select a fallback.
|
||||
*/
|
||||
@ -596,6 +830,15 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return !!this.mergedErrors.length
|
||||
}
|
||||
|
||||
/**
|
||||
* Bound into the context object.
|
||||
*/
|
||||
function blurHandler () {
|
||||
if (this.errorBehavior === 'blur') {
|
||||
this.behavioralErrorVisibility = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
@ -639,7 +882,8 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
inheritAttrs: false,
|
||||
inject: {
|
||||
formulateFormSetter: { default: undefined },
|
||||
formulateFormRegister: { default: undefined }
|
||||
formulateFormRegister: { default: undefined },
|
||||
getFormValues: { default: function () { return function () { return ({}); }; } }
|
||||
},
|
||||
model: {
|
||||
prop: 'formulateValue',
|
||||
@ -698,15 +942,23 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
type: [String, Boolean, Array],
|
||||
default: false
|
||||
},
|
||||
validationBehavior: {
|
||||
validationName: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
errorBehavior: {
|
||||
type: String,
|
||||
default: 'blur',
|
||||
validator: function (value) {
|
||||
return ['blur', 'live'].includes(value)
|
||||
}
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
showErrors: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
@ -715,6 +967,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
defaultId: nanoid(9),
|
||||
localAttributes: {},
|
||||
internalModelProxy: this.formulateValue,
|
||||
behavioralErrorVisibility: (this.errorBehavior === 'live'),
|
||||
validationErrors: []
|
||||
}
|
||||
},
|
||||
@ -768,7 +1021,13 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
var args = ref[1];
|
||||
|
||||
return rule.apply(void 0, [ this$1.context.model ].concat( args ))
|
||||
.then(function (res) { return res ? false : 'Validation error!'; })
|
||||
.then(function (res) { return res ? false : this$1.$formulate.validationMessage(rule.name, {
|
||||
args: args,
|
||||
name: this$1.mergedValidationName,
|
||||
value: this$1.context.model,
|
||||
vm: this$1,
|
||||
formValues: this$1.getFormValues()
|
||||
}); })
|
||||
})
|
||||
)
|
||||
.then(function (result) { return result.filter(function (result) { return result; }); })
|
||||
@ -867,6 +1126,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
attrs: {
|
||||
"data-classification": _vm.classification,
|
||||
"data-has-errors": _vm.hasErrors,
|
||||
"data-is-showing-errors": _vm.hasErrors && _vm.showFieldErrors,
|
||||
"data-type": _vm.type
|
||||
}
|
||||
},
|
||||
@ -929,7 +1189,9 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
})
|
||||
: _vm._e(),
|
||||
_vm._v(" "),
|
||||
_c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } })
|
||||
_vm.showFieldErrors
|
||||
? _c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } })
|
||||
: _vm._e()
|
||||
],
|
||||
1
|
||||
)
|
||||
@ -972,7 +1234,8 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
provide: function provide () {
|
||||
return {
|
||||
formulateFormSetter: this.setFieldValue,
|
||||
formulateFormRegister: this.register
|
||||
formulateFormRegister: this.register,
|
||||
getFormValues: this.getFormValues
|
||||
}
|
||||
},
|
||||
name: 'FormulateForm',
|
||||
@ -1054,6 +1317,9 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
formSubmitted: function formSubmitted () {
|
||||
// perform validation here
|
||||
this.$emit('submit', this.formModel);
|
||||
},
|
||||
getFormValues: function getFormValues () {
|
||||
return this.internalFormModelProxy
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1382,6 +1648,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$a = _vm.context.model,
|
||||
$$el = $event.target,
|
||||
@ -1430,6 +1697,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
checked: _vm._q(_vm.context.model, _vm.context.value)
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
return _vm.$set(_vm.context, "model", _vm.context.value)
|
||||
}
|
||||
@ -1458,6 +1726,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
value: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
@ -1552,6 +1821,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$a = _vm.context.model,
|
||||
$$el = $event.target,
|
||||
@ -1597,6 +1867,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
attrs: { type: "radio" },
|
||||
domProps: { checked: _vm._q(_vm.context.model, null) },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
return _vm.$set(_vm.context, "model", null)
|
||||
}
|
||||
@ -1622,6 +1893,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
attrs: { type: _vm.type },
|
||||
domProps: { value: _vm.context.model },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
@ -1714,6 +1986,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
],
|
||||
attrs: { "data-placeholder-selected": _vm.placeholderSelected },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$selectedVal = Array.prototype.filter
|
||||
.call($event.target.options, function(o) {
|
||||
@ -1866,6 +2139,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
],
|
||||
domProps: { value: _vm.context.model },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
@ -1930,7 +2204,11 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
FormulateInputTextArea: FormulateInputTextArea
|
||||
},
|
||||
library: library,
|
||||
rules: rules
|
||||
rules: rules,
|
||||
locale: 'en',
|
||||
locales: {
|
||||
en: en
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -2000,6 +2278,20 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return this.options.rules
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the validation message for a particular error.
|
||||
*/
|
||||
Formulate.prototype.validationMessage = function validationMessage (rule, validationContext) {
|
||||
var generators = this.options.locales[this.options.locale];
|
||||
if (generators.hasOwnProperty(rule)) {
|
||||
return generators[rule](validationContext)
|
||||
}
|
||||
if (generators.hasOwnProperty('default')) {
|
||||
return generators.default(validationContext)
|
||||
}
|
||||
return 'This field does not have a valid value'
|
||||
};
|
||||
|
||||
var Formulate$1 = new Formulate();
|
||||
|
||||
exports.default = Formulate$1;
|
||||
|
574
dist/formulate.umd.js
vendored
574
dist/formulate.umd.js
vendored
@ -167,6 +167,17 @@
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* How to add an item.
|
||||
* @param {string} item
|
||||
*/
|
||||
function sentence (item) {
|
||||
if (typeof item === 'string') {
|
||||
return item[0].toUpperCase() + item.substr(1)
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array or string return an array of callables.
|
||||
* @param {array|string} validation
|
||||
@ -193,6 +204,7 @@
|
||||
return [rule, []]
|
||||
}
|
||||
if (Array.isArray(rule) && rule.length) {
|
||||
rule = rule.map(function (r) { return r; }); // light clone
|
||||
if (typeof rule[0] === 'string' && rules.hasOwnProperty(rule[0])) {
|
||||
return [rules[rule.shift()], rule]
|
||||
}
|
||||
@ -223,88 +235,6 @@
|
||||
return Promise.resolve(['yes', 'on', '1', 1, true, 'true'].includes(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: must be a value
|
||||
*/
|
||||
required: function (value, isRequired) {
|
||||
if ( isRequired === void 0 ) isRequired = true;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (!isRequired || ['no', 'false'].includes(isRequired)) {
|
||||
return true
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return !!value.length
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return !!value
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return (!value) ? false : !!Object.keys(value).length
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is in an array (stack).
|
||||
*/
|
||||
in: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) !== undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is not in stack.
|
||||
*/
|
||||
not: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) === undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Match the value against a (stack) of patterns or strings
|
||||
*/
|
||||
matches: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(!!stack.find(function (pattern) {
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(value)
|
||||
}
|
||||
return pattern === value
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a string is a valid url
|
||||
*/
|
||||
url: function (value) {
|
||||
return Promise.resolve(isUrl(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
@ -316,6 +246,34 @@
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue > timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha
|
||||
*/
|
||||
alpha: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z]+$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z0-9]+$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
@ -327,45 +285,13 @@
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue < timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
alpha: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-z][A-Z]$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
number: function (value) {
|
||||
return Promise.resolve(!isNaN(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (value, set) {
|
||||
if ( set === void 0 ) set = 'default';
|
||||
|
||||
var sets = {
|
||||
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z0-9]$/
|
||||
};
|
||||
var selectedSet = sets.hasOwnProperty(set) ? set : 'default';
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is between two other values
|
||||
*/
|
||||
between: function (value, from, to) {
|
||||
if ( from === void 0 ) from = 0;
|
||||
if ( to === void 0 ) to = 10;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (from === null || to === null || isNaN(from) || isNaN(to)) {
|
||||
return false
|
||||
@ -383,6 +309,13 @@
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: tests
|
||||
*/
|
||||
@ -392,6 +325,58 @@
|
||||
return Promise.resolve(isEmail.test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is in an array (stack).
|
||||
*/
|
||||
in: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) !== undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Match the value against a (stack) of patterns or strings
|
||||
*/
|
||||
matches: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(!!stack.find(function (pattern) {
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(value)
|
||||
}
|
||||
return pattern === value
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the maximum value of a particular.
|
||||
*/
|
||||
max: function (value, minimum) {
|
||||
if ( minimum === void 0 ) minimum = 10;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
minimum = Number(minimum);
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value);
|
||||
return value <= minimum
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length <= minimum
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length <= minimum
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the file type is correct.
|
||||
*/
|
||||
@ -415,6 +400,8 @@
|
||||
* Check the minimum value of a particular.
|
||||
*/
|
||||
min: function (value, minimum) {
|
||||
if ( minimum === void 0 ) minimum = 1;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
minimum = Number(minimum);
|
||||
if (!isNaN(value)) {
|
||||
@ -432,23 +419,243 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the minimum value of a particular.
|
||||
* Rule: Value is not in stack.
|
||||
*/
|
||||
max: function (value, minimum) {
|
||||
return Promise.resolve((function () {
|
||||
minimum = Number(minimum);
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value);
|
||||
return value <= minimum
|
||||
not: function (value) {
|
||||
var stack = [], len = arguments.length - 1;
|
||||
while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ];
|
||||
|
||||
return Promise.resolve(stack.find(function (item) {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length <= minimum
|
||||
return item === value
|
||||
}) === undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
number: function (value) {
|
||||
return Promise.resolve(!isNaN(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: must be a value
|
||||
*/
|
||||
required: function (value, isRequired) {
|
||||
if ( isRequired === void 0 ) isRequired = true;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (!isRequired || ['no', 'false'].includes(isRequired)) {
|
||||
return true
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length <= minimum
|
||||
return !!value.length
|
||||
}
|
||||
return false
|
||||
if (typeof value === 'string') {
|
||||
return !!value
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return (!value) ? false : !!Object.keys(value).length
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a string is a valid url
|
||||
*/
|
||||
url: function (value) {
|
||||
return Promise.resolve(isUrl(value))
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validation error message generators.
|
||||
*/
|
||||
var en = {
|
||||
|
||||
/**
|
||||
* Valid accepted value.
|
||||
*/
|
||||
accepted: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ("Please accept the " + name + ".")
|
||||
},
|
||||
|
||||
/**
|
||||
* The date is not after.
|
||||
*/
|
||||
after: function (ref) {
|
||||
var name = ref.name;
|
||||
var args = ref.args;
|
||||
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return ((sentence(name)) + " must be after " + (args[0]) + ".")
|
||||
}
|
||||
return ((sentence(name)) + " must be a later date.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The value is not a letter.
|
||||
*/
|
||||
alpha: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " can only contain alphabetical characters.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " can only contain letters and numbers.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The date is not before.
|
||||
*/
|
||||
before: function (ref) {
|
||||
var name = ref.name;
|
||||
var args = ref.args;
|
||||
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return ((sentence(name)) + " must be before " + (args[0]) + ".")
|
||||
}
|
||||
return ((sentence(name)) + " must be an earlier date.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The value is not between two numbers or lengths
|
||||
*/
|
||||
between: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
var args = ref.args;
|
||||
|
||||
if (!isNaN(value)) {
|
||||
return ((sentence(name)) + " must be between " + (args[0]) + " and " + (args[1]) + ".")
|
||||
}
|
||||
return ((sentence(name)) + " must be between " + (args[0]) + " and " + (args[1]) + " characters long.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Is not a valid date.
|
||||
*/
|
||||
date: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " is not a valid date.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render method for error messages.
|
||||
*/
|
||||
default: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return "This field isn’t valid."
|
||||
},
|
||||
|
||||
/**
|
||||
* Is not a valid email address.
|
||||
*/
|
||||
email: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
return (value + " is not a valid email address.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is an allowed value.
|
||||
*/
|
||||
in: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
return ("“" + (sentence(value)) + "” is not an allowed " + name + ".")
|
||||
}
|
||||
return ((sentence(name)) + " is not an allowed value.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is not a match.
|
||||
*/
|
||||
matches: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " is not an allowed value.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The maximum value allowed.
|
||||
*/
|
||||
max: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
var args = ref.args;
|
||||
|
||||
if (!isNaN(value)) {
|
||||
return (name + " must be less than " + (args[0]) + ".")
|
||||
}
|
||||
return (name + " must be less than " + (args[0]) + " characters long.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The maximum value allowed.
|
||||
*/
|
||||
min: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
var args = ref.args;
|
||||
|
||||
if (!isNaN(value)) {
|
||||
return (name + " must be more than " + (args[0]) + ".")
|
||||
}
|
||||
return (name + " must be more than " + (args[0]) + " characters long.")
|
||||
},
|
||||
|
||||
/**
|
||||
* The field is not an allowed value
|
||||
*/
|
||||
not: function (ref) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
return ("“" + value + "” is not an allowed " + name + ".")
|
||||
},
|
||||
|
||||
/**
|
||||
* The field is not a number
|
||||
*/
|
||||
number: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " must be a number.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Required field.
|
||||
*/
|
||||
required: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return ((sentence(name)) + " is required.")
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is not a url.
|
||||
*/
|
||||
url: function (ref) {
|
||||
var name = ref.name;
|
||||
|
||||
return "Please include a valid url."
|
||||
}
|
||||
};
|
||||
|
||||
@ -459,9 +666,6 @@
|
||||
*/
|
||||
var context = {
|
||||
context: function context () {
|
||||
if (this.debug) {
|
||||
console.log(((this.type) + " re-context"));
|
||||
}
|
||||
return defineModel.call(this, Object.assign({}, {type: this.type,
|
||||
value: this.value,
|
||||
name: this.nameOrFallback,
|
||||
@ -470,7 +674,8 @@
|
||||
id: this.id || this.defaultId,
|
||||
label: this.label,
|
||||
labelPosition: this.logicalLabelPosition,
|
||||
attributes: this.elementAttributes},
|
||||
attributes: this.elementAttributes,
|
||||
blurHandler: blurHandler.bind(this)},
|
||||
this.typeContext))
|
||||
},
|
||||
nameOrFallback: nameOrFallback,
|
||||
@ -479,7 +684,9 @@
|
||||
logicalLabelPosition: logicalLabelPosition,
|
||||
isVmodeled: isVmodeled,
|
||||
mergedErrors: mergedErrors,
|
||||
hasErrors: hasErrors
|
||||
hasErrors: hasErrors,
|
||||
showFieldErrors: showFieldErrors,
|
||||
mergedValidationName: mergedValidationName
|
||||
};
|
||||
|
||||
/**
|
||||
@ -539,6 +746,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The validation label to use.
|
||||
*/
|
||||
function mergedValidationName () {
|
||||
if (this.validationName) {
|
||||
return this.validationName
|
||||
}
|
||||
if (typeof this.name === 'string') {
|
||||
return this.name
|
||||
}
|
||||
if (this.label) {
|
||||
return this.label
|
||||
}
|
||||
return this.type
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the field should show it's error (if it has one)
|
||||
* @return {boolean}
|
||||
*/
|
||||
function showFieldErrors () {
|
||||
if (this.showErrors) {
|
||||
return this.showErrors
|
||||
}
|
||||
return this.behavioralErrorVisibility
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the element’s name, or select a fallback.
|
||||
*/
|
||||
@ -599,6 +833,15 @@
|
||||
return !!this.mergedErrors.length
|
||||
}
|
||||
|
||||
/**
|
||||
* Bound into the context object.
|
||||
*/
|
||||
function blurHandler () {
|
||||
if (this.errorBehavior === 'blur') {
|
||||
this.behavioralErrorVisibility = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
@ -642,7 +885,8 @@
|
||||
inheritAttrs: false,
|
||||
inject: {
|
||||
formulateFormSetter: { default: undefined },
|
||||
formulateFormRegister: { default: undefined }
|
||||
formulateFormRegister: { default: undefined },
|
||||
getFormValues: { default: function () { return function () { return ({}); }; } }
|
||||
},
|
||||
model: {
|
||||
prop: 'formulateValue',
|
||||
@ -701,15 +945,23 @@
|
||||
type: [String, Boolean, Array],
|
||||
default: false
|
||||
},
|
||||
validationBehavior: {
|
||||
validationName: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
errorBehavior: {
|
||||
type: String,
|
||||
default: 'blur',
|
||||
validator: function (value) {
|
||||
return ['blur', 'live'].includes(value)
|
||||
}
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
showErrors: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
@ -718,6 +970,7 @@
|
||||
defaultId: nanoid(9),
|
||||
localAttributes: {},
|
||||
internalModelProxy: this.formulateValue,
|
||||
behavioralErrorVisibility: (this.errorBehavior === 'live'),
|
||||
validationErrors: []
|
||||
}
|
||||
},
|
||||
@ -771,7 +1024,13 @@
|
||||
var args = ref[1];
|
||||
|
||||
return rule.apply(void 0, [ this$1.context.model ].concat( args ))
|
||||
.then(function (res) { return res ? false : 'Validation error!'; })
|
||||
.then(function (res) { return res ? false : this$1.$formulate.validationMessage(rule.name, {
|
||||
args: args,
|
||||
name: this$1.mergedValidationName,
|
||||
value: this$1.context.model,
|
||||
vm: this$1,
|
||||
formValues: this$1.getFormValues()
|
||||
}); })
|
||||
})
|
||||
)
|
||||
.then(function (result) { return result.filter(function (result) { return result; }); })
|
||||
@ -870,6 +1129,7 @@
|
||||
attrs: {
|
||||
"data-classification": _vm.classification,
|
||||
"data-has-errors": _vm.hasErrors,
|
||||
"data-is-showing-errors": _vm.hasErrors && _vm.showFieldErrors,
|
||||
"data-type": _vm.type
|
||||
}
|
||||
},
|
||||
@ -932,7 +1192,9 @@
|
||||
})
|
||||
: _vm._e(),
|
||||
_vm._v(" "),
|
||||
_c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } })
|
||||
_vm.showFieldErrors
|
||||
? _c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } })
|
||||
: _vm._e()
|
||||
],
|
||||
1
|
||||
)
|
||||
@ -975,7 +1237,8 @@
|
||||
provide: function provide () {
|
||||
return {
|
||||
formulateFormSetter: this.setFieldValue,
|
||||
formulateFormRegister: this.register
|
||||
formulateFormRegister: this.register,
|
||||
getFormValues: this.getFormValues
|
||||
}
|
||||
},
|
||||
name: 'FormulateForm',
|
||||
@ -1057,6 +1320,9 @@
|
||||
formSubmitted: function formSubmitted () {
|
||||
// perform validation here
|
||||
this.$emit('submit', this.formModel);
|
||||
},
|
||||
getFormValues: function getFormValues () {
|
||||
return this.internalFormModelProxy
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1385,6 +1651,7 @@
|
||||
: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$a = _vm.context.model,
|
||||
$$el = $event.target,
|
||||
@ -1433,6 +1700,7 @@
|
||||
checked: _vm._q(_vm.context.model, _vm.context.value)
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
return _vm.$set(_vm.context, "model", _vm.context.value)
|
||||
}
|
||||
@ -1461,6 +1729,7 @@
|
||||
value: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
@ -1555,6 +1824,7 @@
|
||||
: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$a = _vm.context.model,
|
||||
$$el = $event.target,
|
||||
@ -1600,6 +1870,7 @@
|
||||
attrs: { type: "radio" },
|
||||
domProps: { checked: _vm._q(_vm.context.model, null) },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
return _vm.$set(_vm.context, "model", null)
|
||||
}
|
||||
@ -1625,6 +1896,7 @@
|
||||
attrs: { type: _vm.type },
|
||||
domProps: { value: _vm.context.model },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
@ -1717,6 +1989,7 @@
|
||||
],
|
||||
attrs: { "data-placeholder-selected": _vm.placeholderSelected },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$selectedVal = Array.prototype.filter
|
||||
.call($event.target.options, function(o) {
|
||||
@ -1869,6 +2142,7 @@
|
||||
],
|
||||
domProps: { value: _vm.context.model },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
@ -1933,7 +2207,11 @@
|
||||
FormulateInputTextArea: FormulateInputTextArea
|
||||
},
|
||||
library: library,
|
||||
rules: rules
|
||||
rules: rules,
|
||||
locale: 'en',
|
||||
locales: {
|
||||
en: en
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -2003,6 +2281,20 @@
|
||||
return this.options.rules
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the validation message for a particular error.
|
||||
*/
|
||||
Formulate.prototype.validationMessage = function validationMessage (rule, validationContext) {
|
||||
var generators = this.options.locales[this.options.locale];
|
||||
if (generators.hasOwnProperty(rule)) {
|
||||
return generators[rule](validationContext)
|
||||
}
|
||||
if (generators.hasOwnProperty('default')) {
|
||||
return generators.default(validationContext)
|
||||
}
|
||||
return 'This field does not have a valid value'
|
||||
};
|
||||
|
||||
var Formulate$1 = new Formulate();
|
||||
|
||||
exports.default = Formulate$1;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import library from './libs/library'
|
||||
import rules from './libs/rules'
|
||||
import en from './locales/en'
|
||||
import isPlainObject from 'is-plain-object'
|
||||
import FormulateInput from './FormulateInput.vue'
|
||||
import FormulateForm from './FormulateForm.vue'
|
||||
@ -30,7 +31,11 @@ class Formulate {
|
||||
FormulateInputTextArea
|
||||
},
|
||||
library,
|
||||
rules
|
||||
rules,
|
||||
locale: 'en',
|
||||
locales: {
|
||||
en
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,6 +104,20 @@ class Formulate {
|
||||
rules () {
|
||||
return this.options.rules
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation message for a particular error.
|
||||
*/
|
||||
validationMessage (rule, validationContext) {
|
||||
const generators = this.options.locales[this.options.locale]
|
||||
if (generators.hasOwnProperty(rule)) {
|
||||
return generators[rule](validationContext)
|
||||
}
|
||||
if (generators.hasOwnProperty('default')) {
|
||||
return generators.default(validationContext)
|
||||
}
|
||||
return 'This field does not have a valid value'
|
||||
}
|
||||
}
|
||||
|
||||
export default new Formulate()
|
||||
|
@ -13,7 +13,8 @@ export default {
|
||||
provide () {
|
||||
return {
|
||||
formulateFormSetter: this.setFieldValue,
|
||||
formulateFormRegister: this.register
|
||||
formulateFormRegister: this.register,
|
||||
getFormValues: this.getFormValues
|
||||
}
|
||||
},
|
||||
name: 'FormulateForm',
|
||||
@ -93,6 +94,9 @@ export default {
|
||||
formSubmitted () {
|
||||
// perform validation here
|
||||
this.$emit('submit', this.formModel)
|
||||
},
|
||||
getFormValues () {
|
||||
return this.internalFormModelProxy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
class="formulate-input"
|
||||
:data-classification="classification"
|
||||
:data-has-errors="hasErrors"
|
||||
:data-is-showing-errors="hasErrors && showFieldErrors"
|
||||
:data-type="type"
|
||||
>
|
||||
<div class="formulate-input-wrapper">
|
||||
@ -41,6 +42,7 @@
|
||||
v-text="help"
|
||||
/>
|
||||
<FormulateInputErrors
|
||||
v-if="showFieldErrors"
|
||||
:errors="mergedErrors"
|
||||
/>
|
||||
</div>
|
||||
@ -56,7 +58,8 @@ export default {
|
||||
inheritAttrs: false,
|
||||
inject: {
|
||||
formulateFormSetter: { default: undefined },
|
||||
formulateFormRegister: { default: undefined }
|
||||
formulateFormRegister: { default: undefined },
|
||||
getFormValues: { default: () => () => ({}) }
|
||||
},
|
||||
model: {
|
||||
prop: 'formulateValue',
|
||||
@ -115,15 +118,23 @@ export default {
|
||||
type: [String, Boolean, Array],
|
||||
default: false
|
||||
},
|
||||
validationBehavior: {
|
||||
validationName: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
errorBehavior: {
|
||||
type: String,
|
||||
default: 'blur',
|
||||
validator: function (value) {
|
||||
return ['blur', 'live'].includes(value)
|
||||
}
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
showErrors: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
@ -132,6 +143,7 @@ export default {
|
||||
defaultId: nanoid(9),
|
||||
localAttributes: {},
|
||||
internalModelProxy: this.formulateValue,
|
||||
behavioralErrorVisibility: (this.errorBehavior === 'live'),
|
||||
validationErrors: []
|
||||
}
|
||||
},
|
||||
@ -182,7 +194,13 @@ export default {
|
||||
Promise.all(
|
||||
rules.map(([rule, args]) => {
|
||||
return rule(this.context.model, ...args)
|
||||
.then(res => res ? false : 'Validation error!')
|
||||
.then(res => res ? false : this.$formulate.validationMessage(rule.name, {
|
||||
args,
|
||||
name: this.mergedValidationName,
|
||||
value: this.context.model,
|
||||
vm: this,
|
||||
formValues: this.getFormValues()
|
||||
}))
|
||||
})
|
||||
)
|
||||
.then(result => result.filter(result => result))
|
||||
|
@ -8,6 +8,7 @@
|
||||
:type="type"
|
||||
:value="context.value"
|
||||
v-bind="attributes"
|
||||
@blur="context.blurHandler"
|
||||
>
|
||||
<label
|
||||
class="formulate-input-element-decorator"
|
||||
|
@ -6,6 +6,7 @@
|
||||
v-model="context.model"
|
||||
v-bind="attributes"
|
||||
:data-placeholder-selected="placeholderSelected"
|
||||
@blur="context.blurHandler"
|
||||
>
|
||||
<option
|
||||
v-if="context.placeholder"
|
||||
|
@ -6,6 +6,7 @@
|
||||
v-model="context.model"
|
||||
:type="type"
|
||||
v-bind="attributes"
|
||||
@blur="context.blurHandler"
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -5,6 +5,7 @@
|
||||
<textarea
|
||||
v-model="context.model"
|
||||
v-bind="attributes"
|
||||
@blur="context.blurHandler"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -8,9 +8,6 @@ import { map, arrayify } from './utils'
|
||||
*/
|
||||
export default {
|
||||
context () {
|
||||
if (this.debug) {
|
||||
console.log(`${this.type} re-context`)
|
||||
}
|
||||
return defineModel.call(this, {
|
||||
type: this.type,
|
||||
value: this.value,
|
||||
@ -21,6 +18,7 @@ export default {
|
||||
label: this.label,
|
||||
labelPosition: this.logicalLabelPosition,
|
||||
attributes: this.elementAttributes,
|
||||
blurHandler: blurHandler.bind(this),
|
||||
...this.typeContext
|
||||
})
|
||||
},
|
||||
@ -30,7 +28,9 @@ export default {
|
||||
logicalLabelPosition,
|
||||
isVmodeled,
|
||||
mergedErrors,
|
||||
hasErrors
|
||||
hasErrors,
|
||||
showFieldErrors,
|
||||
mergedValidationName
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,6 +88,33 @@ function logicalLabelPosition () {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The validation label to use.
|
||||
*/
|
||||
function mergedValidationName () {
|
||||
if (this.validationName) {
|
||||
return this.validationName
|
||||
}
|
||||
if (typeof this.name === 'string') {
|
||||
return this.name
|
||||
}
|
||||
if (this.label) {
|
||||
return this.label
|
||||
}
|
||||
return this.type
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the field should show it's error (if it has one)
|
||||
* @return {boolean}
|
||||
*/
|
||||
function showFieldErrors () {
|
||||
if (this.showErrors) {
|
||||
return this.showErrors
|
||||
}
|
||||
return this.behavioralErrorVisibility
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the element’s name, or select a fallback.
|
||||
*/
|
||||
@ -148,6 +175,15 @@ function hasErrors () {
|
||||
return !!this.mergedErrors.length
|
||||
}
|
||||
|
||||
/**
|
||||
* Bound into the context object.
|
||||
*/
|
||||
function blurHandler () {
|
||||
if (this.errorBehavior === 'blur') {
|
||||
this.behavioralErrorVisibility = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
|
@ -12,6 +12,184 @@ export default {
|
||||
return Promise.resolve(['yes', 'on', '1', 1, true, 'true'].includes(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
after: function (value, compare = false) {
|
||||
const timestamp = Date.parse(compare || new Date())
|
||||
const fieldValue = Date.parse(value)
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue > timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha
|
||||
*/
|
||||
alpha: function (value, set = 'default') {
|
||||
const sets = {
|
||||
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z]+$/
|
||||
}
|
||||
const selectedSet = sets.hasOwnProperty(set) ? set : 'default'
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (value, set = 'default') {
|
||||
const sets = {
|
||||
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z0-9]+$/
|
||||
}
|
||||
const selectedSet = sets.hasOwnProperty(set) ? set : 'default'
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
before: function (value, compare = false) {
|
||||
const timestamp = Date.parse(compare || new Date())
|
||||
const fieldValue = Date.parse(value)
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue < timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is between two other values
|
||||
*/
|
||||
between: function (value, from = 0, to = 10) {
|
||||
return Promise.resolve((() => {
|
||||
if (from === null || to === null || isNaN(from) || isNaN(to)) {
|
||||
return false
|
||||
}
|
||||
from = Number(from)
|
||||
to = Number(to)
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value)
|
||||
return (value > from && value < to)
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length > from && value.length < to
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: tests
|
||||
*/
|
||||
email: function (value) {
|
||||
// eslint-disable-next-line
|
||||
const isEmail = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i
|
||||
return Promise.resolve(isEmail.test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is in an array (stack).
|
||||
*/
|
||||
in: function (value, ...stack) {
|
||||
return Promise.resolve(stack.find(item => {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) !== undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Match the value against a (stack) of patterns or strings
|
||||
*/
|
||||
matches: function (value, ...stack) {
|
||||
return Promise.resolve(!!stack.find(pattern => {
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(value)
|
||||
}
|
||||
return pattern === value
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the maximum value of a particular.
|
||||
*/
|
||||
max: function (value, minimum = 10) {
|
||||
return Promise.resolve((() => {
|
||||
minimum = Number(minimum)
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value)
|
||||
return value <= minimum
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length <= minimum
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length <= minimum
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the file type is correct.
|
||||
*/
|
||||
mime: function (files, ...types) {
|
||||
return Promise.resolve((() => {
|
||||
if (typeof window !== 'undefined' && typeof FileReader !== 'undefined' && typeof Blob !== 'undefined') {
|
||||
for (const i in files) {
|
||||
if (!types.includes(files[i].type)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the minimum value of a particular.
|
||||
*/
|
||||
min: function (value, minimum = 1) {
|
||||
return Promise.resolve((() => {
|
||||
minimum = Number(minimum)
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value)
|
||||
return value >= minimum
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length >= minimum
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length >= minimum
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is not in stack.
|
||||
*/
|
||||
not: function (value, ...stack) {
|
||||
return Promise.resolve(stack.find(item => {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) === undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
number: function (value) {
|
||||
return Promise.resolve(!isNaN(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: must be a value
|
||||
*/
|
||||
@ -33,188 +211,10 @@ export default {
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is in an array (stack).
|
||||
*/
|
||||
in: function (value, ...stack) {
|
||||
return Promise.resolve(stack.find(item => {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) !== undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Value is not in stack.
|
||||
*/
|
||||
not: function (value, ...stack) {
|
||||
return Promise.resolve(stack.find(item => {
|
||||
if (typeof item === 'object') {
|
||||
return shallowEqualObjects(item, value)
|
||||
}
|
||||
return item === value
|
||||
}) === undefined)
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Match the value against a (stack) of patterns or strings
|
||||
*/
|
||||
matches: function (value, ...stack) {
|
||||
return Promise.resolve(!!stack.find(pattern => {
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(value)
|
||||
}
|
||||
return pattern === value
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a string is a valid url
|
||||
*/
|
||||
url: function (value) {
|
||||
return Promise.resolve(isUrl(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
after: function (value, compare = false) {
|
||||
const timestamp = Date.parse(compare || new Date())
|
||||
const fieldValue = Date.parse(value)
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue > timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if a value is after a given date. Defaults to current time
|
||||
*/
|
||||
before: function (value, compare = false) {
|
||||
const timestamp = Date.parse(compare || new Date())
|
||||
const fieldValue = Date.parse(value)
|
||||
return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue < timestamp))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
alpha: function (value, set = 'default') {
|
||||
const sets = {
|
||||
default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-z][A-Z]$/
|
||||
}
|
||||
const selectedSet = sets.hasOwnProperty(set) ? set : 'default'
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is only alpha numeric
|
||||
*/
|
||||
number: function (value) {
|
||||
return Promise.resolve(!isNaN(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function (value, set = 'default') {
|
||||
const sets = {
|
||||
default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/,
|
||||
latin: /^[a-zA-Z0-9]$/
|
||||
}
|
||||
const selectedSet = sets.hasOwnProperty(set) ? set : 'default'
|
||||
return Promise.resolve(sets[selectedSet].test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is between two other values
|
||||
*/
|
||||
between: function (value, from, to) {
|
||||
return Promise.resolve((() => {
|
||||
if (from === null || to === null || isNaN(from) || isNaN(to)) {
|
||||
return false
|
||||
}
|
||||
from = Number(from)
|
||||
to = Number(to)
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value)
|
||||
return (value > from && value < to)
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length > from && value.length < to
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: tests
|
||||
*/
|
||||
email: function (value) {
|
||||
// eslint-disable-next-line
|
||||
const isEmail = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i
|
||||
return Promise.resolve(isEmail.test(value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the file type is correct.
|
||||
*/
|
||||
mime: function (files, ...types) {
|
||||
return Promise.resolve((() => {
|
||||
if (typeof window !== 'undefined' && typeof FileReader !== 'undefined' && typeof Blob !== 'undefined') {
|
||||
for (const i in files) {
|
||||
if (!types.includes(files[i].type)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the minimum value of a particular.
|
||||
*/
|
||||
min: function (value, minimum) {
|
||||
return Promise.resolve((() => {
|
||||
minimum = Number(minimum)
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value)
|
||||
return value >= minimum
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length >= minimum
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length >= minimum
|
||||
}
|
||||
return false
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the minimum value of a particular.
|
||||
*/
|
||||
max: function (value, minimum) {
|
||||
return Promise.resolve((() => {
|
||||
minimum = Number(minimum)
|
||||
if (!isNaN(value)) {
|
||||
value = Number(value)
|
||||
return value <= minimum
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.length <= minimum
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length <= minimum
|
||||
}
|
||||
return false
|
||||
})())
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* Function to map over an object.
|
||||
* @param {Object} obj An object to map over
|
||||
@ -90,6 +89,17 @@ export function arrayify (item) {
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* How to add an item.
|
||||
* @param {string} item
|
||||
*/
|
||||
export function sentence (item) {
|
||||
if (typeof item === 'string') {
|
||||
return item[0].toUpperCase() + item.substr(1)
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array or string return an array of callables.
|
||||
* @param {array|string} validation
|
||||
@ -116,6 +126,7 @@ function parseRule (rule, rules) {
|
||||
return [rule, []]
|
||||
}
|
||||
if (Array.isArray(rule) && rule.length) {
|
||||
rule = rule.map(r => r) // light clone
|
||||
if (typeof rule[0] === 'string' && rules.hasOwnProperty(rule[0])) {
|
||||
return [rules[rule.shift()], rule]
|
||||
}
|
||||
|
143
src/locales/en.js
Normal file
143
src/locales/en.js
Normal file
@ -0,0 +1,143 @@
|
||||
import { sentence as s } from '../libs/utils'
|
||||
/**
|
||||
* Validation error message generators.
|
||||
*/
|
||||
export default {
|
||||
|
||||
/**
|
||||
* Valid accepted value.
|
||||
*/
|
||||
accepted: function ({ name }) {
|
||||
return `Please accept the ${name}.`
|
||||
},
|
||||
|
||||
/**
|
||||
* The date is not after.
|
||||
*/
|
||||
after: function ({ name, args }) {
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return `${s(name)} must be after ${args[0]}.`
|
||||
}
|
||||
return `${s(name)} must be a later date.`
|
||||
},
|
||||
|
||||
/**
|
||||
* The value is not a letter.
|
||||
*/
|
||||
alpha: function ({ name }) {
|
||||
return `${s(name)} can only contain alphabetical characters.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: checks if the value is alpha numeric
|
||||
*/
|
||||
alphanumeric: function ({ name }) {
|
||||
return `${s(name)} can only contain letters and numbers.`
|
||||
},
|
||||
|
||||
/**
|
||||
* The date is not before.
|
||||
*/
|
||||
before: function ({ name, args }) {
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return `${s(name)} must be before ${args[0]}.`
|
||||
}
|
||||
return `${s(name)} must be an earlier date.`
|
||||
},
|
||||
|
||||
/**
|
||||
* The value is not between two numbers or lengths
|
||||
*/
|
||||
between: function ({ name, value, args }) {
|
||||
if (!isNaN(value)) {
|
||||
return `${s(name)} must be between ${args[0]} and ${args[1]}.`
|
||||
}
|
||||
return `${s(name)} must be between ${args[0]} and ${args[1]} characters long.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Is not a valid date.
|
||||
*/
|
||||
date: function ({ name }) {
|
||||
return `${s(name)} is not a valid date.`
|
||||
},
|
||||
|
||||
/**
|
||||
* The default render method for error messages.
|
||||
*/
|
||||
default: function ({ name }) {
|
||||
return `This field isn’t valid.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Is not a valid email address.
|
||||
*/
|
||||
email: function ({ name, value }) {
|
||||
return `${value} is not a valid email address.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is an allowed value.
|
||||
*/
|
||||
in: function ({ name, value }) {
|
||||
if (typeof value === 'string') {
|
||||
return `“${s(value)}” is not an allowed ${name}.`
|
||||
}
|
||||
return `${s(name)} is not an allowed value.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is not a match.
|
||||
*/
|
||||
matches: function ({ name }) {
|
||||
return `${s(name)} is not an allowed value.`
|
||||
},
|
||||
|
||||
/**
|
||||
* The maximum value allowed.
|
||||
*/
|
||||
max: function ({ name, value, args }) {
|
||||
if (!isNaN(value)) {
|
||||
return `${name} must be less than ${args[0]}.`
|
||||
}
|
||||
return `${name} must be less than ${args[0]} characters long.`
|
||||
},
|
||||
|
||||
/**
|
||||
* The maximum value allowed.
|
||||
*/
|
||||
min: function ({ name, value, args }) {
|
||||
if (!isNaN(value)) {
|
||||
return `${name} must be more than ${args[0]}.`
|
||||
}
|
||||
return `${name} must be more than ${args[0]} characters long.`
|
||||
},
|
||||
|
||||
/**
|
||||
* The field is not an allowed value
|
||||
*/
|
||||
not: function ({ name, value }) {
|
||||
return `“${value}” is not an allowed ${name}.`
|
||||
},
|
||||
|
||||
/**
|
||||
* The field is not a number
|
||||
*/
|
||||
number: function ({ name }) {
|
||||
return `${s(name)} must be a number.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Required field.
|
||||
*/
|
||||
required: function ({ name }) {
|
||||
return `${s(name)} is required.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is not a url.
|
||||
*/
|
||||
url: function ({ name }) {
|
||||
return `Please include a valid url.`
|
||||
}
|
||||
}
|
@ -165,22 +165,49 @@ describe('FormulateInputText', () => {
|
||||
})
|
||||
|
||||
it('accepts a single string as an error prop', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', error: 'This is an error' } })
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errorBehavior: 'live', error: 'This is an error' } })
|
||||
expect(wrapper.find('.formulate-input-errors').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('accepts an array as errors prop', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errors: ['This is an error', 'this is another'] } })
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errorBehavior: 'live', errors: ['This is an error', 'this is another'] } })
|
||||
expect(wrapper.findAll('.formulate-input-error').length).toBe(2)
|
||||
})
|
||||
|
||||
it('removes any duplicate errors', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errors: ['This is an error', 'This is an error'] } })
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errorBehavior: 'live', errors: ['This is an error', 'This is an error'] } })
|
||||
expect(wrapper.findAll('.formulate-input-error').length).toBe(1)
|
||||
})
|
||||
|
||||
it('adds data-has-errors when there are errors', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errors: ['This is an error', 'This is an error'] } })
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errorBehavior: 'live', errors: ['This is an error', 'This is an error'] } })
|
||||
expect(wrapper.find('[data-has-errors]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('does not initially show error-behavior blur errors', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errorBehavior: 'blur', errors: ['Bad input'] } })
|
||||
expect(wrapper.find('[data-has-errors]').exists()).toBe(true)
|
||||
expect(wrapper.find('[data-is-showing-errors]').exists()).toBe(false)
|
||||
expect(wrapper.findAll('.formulate-input-errors').exists()).toBe(false)
|
||||
})
|
||||
|
||||
|
||||
it('allows error-behavior blur to be overridden with show-errors', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errorBehavior: 'blur', showErrors: true, errors: ['Bad input'] } })
|
||||
expect(wrapper.find('[data-has-errors]').exists()).toBe(true)
|
||||
expect(wrapper.find('[data-is-showing-errors]').exists()).toBe(true)
|
||||
expect(wrapper.findAll('.formulate-input-errors').exists()).toBe(true)
|
||||
expect(wrapper.findAll('.formulate-input-error').length).toBe(1)
|
||||
})
|
||||
|
||||
it('shows errors on blur with error-behavior blur', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', errorBehavior: 'blur', errors: ['Bad input'] } })
|
||||
expect(wrapper.find('[data-has-errors]').exists()).toBe(true)
|
||||
expect(wrapper.find('[data-is-showing-errors]').exists()).toBe(false)
|
||||
expect(wrapper.findAll('.formulate-input-errors').exists()).toBe(false)
|
||||
wrapper.find('input').trigger('blur')
|
||||
expect(wrapper.find('[data-is-showing-errors]').exists()).toBe(true)
|
||||
expect(wrapper.findAll('.formulate-input-errors').exists()).toBe(true)
|
||||
expect(wrapper.findAll('.formulate-input-error').length).toBe(1)
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user