Initial tests written for validation parsing and rules
This commit is contained in:
parent
9522459600
commit
a53edaa342
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -1,3 +1,6 @@
|
||||
{
|
||||
"jest.showCoverageOnLoad": true
|
||||
"jest.showCoverageOnLoad": true,
|
||||
"cSpell.words": [
|
||||
"arrayify"
|
||||
]
|
||||
}
|
||||
|
280
dist/formulate.esm.js
vendored
280
dist/formulate.esm.js
vendored
@ -140,6 +140,26 @@ function shallowEqualObjects (objA, objB) {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, object, falsey, or array - return an array.
|
||||
* @param {mixed} item
|
||||
*/
|
||||
function arrayify (item) {
|
||||
if (!item) {
|
||||
return []
|
||||
}
|
||||
if (typeof item === 'string') {
|
||||
return [item]
|
||||
}
|
||||
if (Array.isArray(item)) {
|
||||
return item
|
||||
}
|
||||
if (typeof item === 'object') {
|
||||
return Object.values(item)
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* For a single instance of an input, export all of the context needed to fully
|
||||
* render that element.
|
||||
@ -165,7 +185,8 @@ var context = {
|
||||
typeContext: typeContext,
|
||||
elementAttributes: elementAttributes,
|
||||
logicalLabelPosition: logicalLabelPosition,
|
||||
isVmodeled: isVmodeled
|
||||
isVmodeled: isVmodeled,
|
||||
mergedErrors: mergedErrors
|
||||
};
|
||||
|
||||
/**
|
||||
@ -268,6 +289,16 @@ function createOptionList (options) {
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* The merged errors computed property.
|
||||
*/
|
||||
function mergedErrors () {
|
||||
return arrayify(this.errors)
|
||||
.concat(arrayify(this.error))
|
||||
.concat(arrayify(this.validationErrors))
|
||||
.reduce(function (errors, err) { return !errors.includes(err) ? errors.concat(err) : errors; }, [])
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
@ -361,6 +392,14 @@ var script = {
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
errors: {
|
||||
type: [String, Array, Boolean],
|
||||
default: false
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data: function data () {
|
||||
@ -560,8 +599,11 @@ var __vue_render__ = function() {
|
||||
staticClass: "formulate-input-help",
|
||||
domProps: { textContent: _vm._s(_vm.help) }
|
||||
})
|
||||
: _vm._e()
|
||||
]
|
||||
: _vm._e(),
|
||||
_vm._v(" "),
|
||||
_c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } })
|
||||
],
|
||||
1
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__ = [];
|
||||
@ -742,6 +784,87 @@ __vue_render__$1._withStripped = true;
|
||||
undefined
|
||||
);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
var script$2 = {
|
||||
props: {
|
||||
errors: {
|
||||
type: [Boolean, Array],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$2 = script$2;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$2 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
return _vm.errors.length
|
||||
? _c(
|
||||
"ul",
|
||||
{ staticClass: "formulate-input-errors" },
|
||||
_vm._l(_vm.errors, function(error) {
|
||||
return _c("li", {
|
||||
key: error,
|
||||
staticClass: "formulate-input-error",
|
||||
domProps: { innerHTML: _vm._s(error) }
|
||||
})
|
||||
}),
|
||||
0
|
||||
)
|
||||
: _vm._e()
|
||||
};
|
||||
var __vue_staticRenderFns__$2 = [];
|
||||
__vue_render__$2._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$2 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$2 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$2 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$2 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
|
||||
/* style inject shadow dom */
|
||||
|
||||
|
||||
|
||||
var FormulateInputErrors = normalizeComponent(
|
||||
{ render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
|
||||
__vue_inject_styles__$2,
|
||||
__vue_script__$2,
|
||||
__vue_scope_id__$2,
|
||||
__vue_is_functional_template__$2,
|
||||
__vue_module_identifier__$2,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@ -757,7 +880,7 @@ __vue_render__$1._withStripped = true;
|
||||
//
|
||||
|
||||
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
|
||||
var script$2 = {
|
||||
var script$3 = {
|
||||
name: 'FormulateInputGroup',
|
||||
props: {
|
||||
context: {
|
||||
@ -795,10 +918,10 @@ var script$2 = {
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$2 = script$2;
|
||||
var __vue_script__$3 = script$3;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$2 = function() {
|
||||
var __vue_render__$3 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -830,17 +953,17 @@ var __vue_render__$2 = function() {
|
||||
1
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$2 = [];
|
||||
__vue_render__$2._withStripped = true;
|
||||
var __vue_staticRenderFns__$3 = [];
|
||||
__vue_render__$3._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$2 = undefined;
|
||||
var __vue_inject_styles__$3 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$2 = undefined;
|
||||
var __vue_scope_id__$3 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$2 = undefined;
|
||||
var __vue_module_identifier__$3 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$2 = false;
|
||||
var __vue_is_functional_template__$3 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -850,12 +973,12 @@ __vue_render__$2._withStripped = true;
|
||||
|
||||
|
||||
var FormulateInputGroup = normalizeComponent(
|
||||
{ render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
|
||||
__vue_inject_styles__$2,
|
||||
__vue_script__$2,
|
||||
__vue_scope_id__$2,
|
||||
__vue_is_functional_template__$2,
|
||||
__vue_module_identifier__$2,
|
||||
{ render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 },
|
||||
__vue_inject_styles__$3,
|
||||
__vue_script__$3,
|
||||
__vue_scope_id__$3,
|
||||
__vue_is_functional_template__$3,
|
||||
__vue_module_identifier__$3,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -890,16 +1013,16 @@ var FormulateInputMixin = {
|
||||
|
||||
//
|
||||
|
||||
var script$3 = {
|
||||
var script$4 = {
|
||||
name: 'FormulateInputBox',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$3 = script$3;
|
||||
var __vue_script__$4 = script$4;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$3 = function() {
|
||||
var __vue_render__$4 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1028,17 +1151,17 @@ var __vue_render__$3 = function() {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$3 = [];
|
||||
__vue_render__$3._withStripped = true;
|
||||
var __vue_staticRenderFns__$4 = [];
|
||||
__vue_render__$4._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$3 = undefined;
|
||||
var __vue_inject_styles__$4 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$3 = undefined;
|
||||
var __vue_scope_id__$4 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$3 = undefined;
|
||||
var __vue_module_identifier__$4 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$3 = false;
|
||||
var __vue_is_functional_template__$4 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1048,12 +1171,12 @@ __vue_render__$3._withStripped = true;
|
||||
|
||||
|
||||
var FormulateInputBox = normalizeComponent(
|
||||
{ render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 },
|
||||
__vue_inject_styles__$3,
|
||||
__vue_script__$3,
|
||||
__vue_scope_id__$3,
|
||||
__vue_is_functional_template__$3,
|
||||
__vue_module_identifier__$3,
|
||||
{ render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 },
|
||||
__vue_inject_styles__$4,
|
||||
__vue_script__$4,
|
||||
__vue_scope_id__$4,
|
||||
__vue_is_functional_template__$4,
|
||||
__vue_module_identifier__$4,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1062,16 +1185,16 @@ __vue_render__$3._withStripped = true;
|
||||
|
||||
//
|
||||
|
||||
var script$4 = {
|
||||
var script$5 = {
|
||||
name: 'FormulateInputText',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$4 = script$4;
|
||||
var __vue_script__$5 = script$5;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$4 = function() {
|
||||
var __vue_render__$5 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1187,17 +1310,17 @@ var __vue_render__$4 = function() {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$4 = [];
|
||||
__vue_render__$4._withStripped = true;
|
||||
var __vue_staticRenderFns__$5 = [];
|
||||
__vue_render__$5._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$4 = undefined;
|
||||
var __vue_inject_styles__$5 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$4 = undefined;
|
||||
var __vue_scope_id__$5 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$4 = undefined;
|
||||
var __vue_module_identifier__$5 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$4 = false;
|
||||
var __vue_is_functional_template__$5 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1207,12 +1330,12 @@ __vue_render__$4._withStripped = true;
|
||||
|
||||
|
||||
var FormulateInputText = normalizeComponent(
|
||||
{ render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 },
|
||||
__vue_inject_styles__$4,
|
||||
__vue_script__$4,
|
||||
__vue_scope_id__$4,
|
||||
__vue_is_functional_template__$4,
|
||||
__vue_module_identifier__$4,
|
||||
{ render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 },
|
||||
__vue_inject_styles__$5,
|
||||
__vue_script__$5,
|
||||
__vue_scope_id__$5,
|
||||
__vue_is_functional_template__$5,
|
||||
__vue_module_identifier__$5,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1221,7 +1344,7 @@ __vue_render__$4._withStripped = true;
|
||||
|
||||
//
|
||||
|
||||
var script$5 = {
|
||||
var script$6 = {
|
||||
name: 'FormulateInputSelect',
|
||||
mixins: [FormulateInputMixin],
|
||||
computed: {
|
||||
@ -1238,10 +1361,10 @@ var script$5 = {
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$5 = script$5;
|
||||
var __vue_script__$6 = script$6;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$5 = function() {
|
||||
var __vue_render__$6 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1348,17 +1471,17 @@ var __vue_render__$5 = function() {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$5 = [];
|
||||
__vue_render__$5._withStripped = true;
|
||||
var __vue_staticRenderFns__$6 = [];
|
||||
__vue_render__$6._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$5 = undefined;
|
||||
var __vue_inject_styles__$6 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$5 = undefined;
|
||||
var __vue_scope_id__$6 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$5 = undefined;
|
||||
var __vue_module_identifier__$6 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$5 = false;
|
||||
var __vue_is_functional_template__$6 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1368,12 +1491,12 @@ __vue_render__$5._withStripped = true;
|
||||
|
||||
|
||||
var FormulateInputSelect = normalizeComponent(
|
||||
{ render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 },
|
||||
__vue_inject_styles__$5,
|
||||
__vue_script__$5,
|
||||
__vue_scope_id__$5,
|
||||
__vue_is_functional_template__$5,
|
||||
__vue_module_identifier__$5,
|
||||
{ render: __vue_render__$6, staticRenderFns: __vue_staticRenderFns__$6 },
|
||||
__vue_inject_styles__$6,
|
||||
__vue_script__$6,
|
||||
__vue_scope_id__$6,
|
||||
__vue_is_functional_template__$6,
|
||||
__vue_module_identifier__$6,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1382,16 +1505,16 @@ __vue_render__$5._withStripped = true;
|
||||
|
||||
//
|
||||
|
||||
var script$6 = {
|
||||
var script$7 = {
|
||||
name: 'FormulateInputTextArea',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$6 = script$6;
|
||||
var __vue_script__$7 = script$7;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$6 = function() {
|
||||
var __vue_render__$7 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1431,17 +1554,17 @@ var __vue_render__$6 = function() {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$6 = [];
|
||||
__vue_render__$6._withStripped = true;
|
||||
var __vue_staticRenderFns__$7 = [];
|
||||
__vue_render__$7._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$6 = undefined;
|
||||
var __vue_inject_styles__$7 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$6 = undefined;
|
||||
var __vue_scope_id__$7 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$6 = undefined;
|
||||
var __vue_module_identifier__$7 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$6 = false;
|
||||
var __vue_is_functional_template__$7 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1451,12 +1574,12 @@ __vue_render__$6._withStripped = true;
|
||||
|
||||
|
||||
var FormulateInputTextArea = normalizeComponent(
|
||||
{ render: __vue_render__$6, staticRenderFns: __vue_staticRenderFns__$6 },
|
||||
__vue_inject_styles__$6,
|
||||
__vue_script__$6,
|
||||
__vue_scope_id__$6,
|
||||
__vue_is_functional_template__$6,
|
||||
__vue_module_identifier__$6,
|
||||
{ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 },
|
||||
__vue_inject_styles__$7,
|
||||
__vue_script__$7,
|
||||
__vue_scope_id__$7,
|
||||
__vue_is_functional_template__$7,
|
||||
__vue_module_identifier__$7,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1471,6 +1594,7 @@ var Formulate = function Formulate () {
|
||||
components: {
|
||||
FormulateForm: FormulateForm,
|
||||
FormulateInput: FormulateInput,
|
||||
FormulateInputErrors: FormulateInputErrors,
|
||||
FormulateInputBox: FormulateInputBox,
|
||||
FormulateInputText: FormulateInputText,
|
||||
FormulateInputGroup: FormulateInputGroup,
|
||||
|
280
dist/formulate.min.js
vendored
280
dist/formulate.min.js
vendored
@ -143,6 +143,26 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, object, falsey, or array - return an array.
|
||||
* @param {mixed} item
|
||||
*/
|
||||
function arrayify (item) {
|
||||
if (!item) {
|
||||
return []
|
||||
}
|
||||
if (typeof item === 'string') {
|
||||
return [item]
|
||||
}
|
||||
if (Array.isArray(item)) {
|
||||
return item
|
||||
}
|
||||
if (typeof item === 'object') {
|
||||
return Object.values(item)
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* For a single instance of an input, export all of the context needed to fully
|
||||
* render that element.
|
||||
@ -168,7 +188,8 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
typeContext: typeContext,
|
||||
elementAttributes: elementAttributes,
|
||||
logicalLabelPosition: logicalLabelPosition,
|
||||
isVmodeled: isVmodeled
|
||||
isVmodeled: isVmodeled,
|
||||
mergedErrors: mergedErrors
|
||||
};
|
||||
|
||||
/**
|
||||
@ -271,6 +292,16 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* The merged errors computed property.
|
||||
*/
|
||||
function mergedErrors () {
|
||||
return arrayify(this.errors)
|
||||
.concat(arrayify(this.error))
|
||||
.concat(arrayify(this.validationErrors))
|
||||
.reduce(function (errors, err) { return !errors.includes(err) ? errors.concat(err) : errors; }, [])
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
@ -364,6 +395,14 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
errors: {
|
||||
type: [String, Array, Boolean],
|
||||
default: false
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data: function data () {
|
||||
@ -563,8 +602,11 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
staticClass: "formulate-input-help",
|
||||
domProps: { textContent: _vm._s(_vm.help) }
|
||||
})
|
||||
: _vm._e()
|
||||
]
|
||||
: _vm._e(),
|
||||
_vm._v(" "),
|
||||
_c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } })
|
||||
],
|
||||
1
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__ = [];
|
||||
@ -745,6 +787,87 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
undefined
|
||||
);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
var script$2 = {
|
||||
props: {
|
||||
errors: {
|
||||
type: [Boolean, Array],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$2 = script$2;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$2 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
return _vm.errors.length
|
||||
? _c(
|
||||
"ul",
|
||||
{ staticClass: "formulate-input-errors" },
|
||||
_vm._l(_vm.errors, function(error) {
|
||||
return _c("li", {
|
||||
key: error,
|
||||
staticClass: "formulate-input-error",
|
||||
domProps: { innerHTML: _vm._s(error) }
|
||||
})
|
||||
}),
|
||||
0
|
||||
)
|
||||
: _vm._e()
|
||||
};
|
||||
var __vue_staticRenderFns__$2 = [];
|
||||
__vue_render__$2._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$2 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$2 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$2 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$2 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
|
||||
/* style inject shadow dom */
|
||||
|
||||
|
||||
|
||||
var FormulateInputErrors = normalizeComponent(
|
||||
{ render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
|
||||
__vue_inject_styles__$2,
|
||||
__vue_script__$2,
|
||||
__vue_scope_id__$2,
|
||||
__vue_is_functional_template__$2,
|
||||
__vue_module_identifier__$2,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@ -760,7 +883,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
//
|
||||
|
||||
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
|
||||
var script$2 = {
|
||||
var script$3 = {
|
||||
name: 'FormulateInputGroup',
|
||||
props: {
|
||||
context: {
|
||||
@ -798,10 +921,10 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$2 = script$2;
|
||||
var __vue_script__$3 = script$3;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$2 = function() {
|
||||
var __vue_render__$3 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -833,17 +956,17 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
1
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$2 = [];
|
||||
__vue_render__$2._withStripped = true;
|
||||
var __vue_staticRenderFns__$3 = [];
|
||||
__vue_render__$3._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$2 = undefined;
|
||||
var __vue_inject_styles__$3 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$2 = undefined;
|
||||
var __vue_scope_id__$3 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$2 = undefined;
|
||||
var __vue_module_identifier__$3 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$2 = false;
|
||||
var __vue_is_functional_template__$3 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -853,12 +976,12 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
|
||||
|
||||
var FormulateInputGroup = normalizeComponent(
|
||||
{ render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
|
||||
__vue_inject_styles__$2,
|
||||
__vue_script__$2,
|
||||
__vue_scope_id__$2,
|
||||
__vue_is_functional_template__$2,
|
||||
__vue_module_identifier__$2,
|
||||
{ render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 },
|
||||
__vue_inject_styles__$3,
|
||||
__vue_script__$3,
|
||||
__vue_scope_id__$3,
|
||||
__vue_is_functional_template__$3,
|
||||
__vue_module_identifier__$3,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -893,16 +1016,16 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
|
||||
//
|
||||
|
||||
var script$3 = {
|
||||
var script$4 = {
|
||||
name: 'FormulateInputBox',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$3 = script$3;
|
||||
var __vue_script__$4 = script$4;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$3 = function() {
|
||||
var __vue_render__$4 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1031,17 +1154,17 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$3 = [];
|
||||
__vue_render__$3._withStripped = true;
|
||||
var __vue_staticRenderFns__$4 = [];
|
||||
__vue_render__$4._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$3 = undefined;
|
||||
var __vue_inject_styles__$4 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$3 = undefined;
|
||||
var __vue_scope_id__$4 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$3 = undefined;
|
||||
var __vue_module_identifier__$4 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$3 = false;
|
||||
var __vue_is_functional_template__$4 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1051,12 +1174,12 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
|
||||
|
||||
var FormulateInputBox = normalizeComponent(
|
||||
{ render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 },
|
||||
__vue_inject_styles__$3,
|
||||
__vue_script__$3,
|
||||
__vue_scope_id__$3,
|
||||
__vue_is_functional_template__$3,
|
||||
__vue_module_identifier__$3,
|
||||
{ render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 },
|
||||
__vue_inject_styles__$4,
|
||||
__vue_script__$4,
|
||||
__vue_scope_id__$4,
|
||||
__vue_is_functional_template__$4,
|
||||
__vue_module_identifier__$4,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1065,16 +1188,16 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
|
||||
//
|
||||
|
||||
var script$4 = {
|
||||
var script$5 = {
|
||||
name: 'FormulateInputText',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$4 = script$4;
|
||||
var __vue_script__$5 = script$5;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$4 = function() {
|
||||
var __vue_render__$5 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1190,17 +1313,17 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$4 = [];
|
||||
__vue_render__$4._withStripped = true;
|
||||
var __vue_staticRenderFns__$5 = [];
|
||||
__vue_render__$5._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$4 = undefined;
|
||||
var __vue_inject_styles__$5 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$4 = undefined;
|
||||
var __vue_scope_id__$5 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$4 = undefined;
|
||||
var __vue_module_identifier__$5 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$4 = false;
|
||||
var __vue_is_functional_template__$5 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1210,12 +1333,12 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
|
||||
|
||||
var FormulateInputText = normalizeComponent(
|
||||
{ render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 },
|
||||
__vue_inject_styles__$4,
|
||||
__vue_script__$4,
|
||||
__vue_scope_id__$4,
|
||||
__vue_is_functional_template__$4,
|
||||
__vue_module_identifier__$4,
|
||||
{ render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 },
|
||||
__vue_inject_styles__$5,
|
||||
__vue_script__$5,
|
||||
__vue_scope_id__$5,
|
||||
__vue_is_functional_template__$5,
|
||||
__vue_module_identifier__$5,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1224,7 +1347,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
|
||||
//
|
||||
|
||||
var script$5 = {
|
||||
var script$6 = {
|
||||
name: 'FormulateInputSelect',
|
||||
mixins: [FormulateInputMixin],
|
||||
computed: {
|
||||
@ -1241,10 +1364,10 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$5 = script$5;
|
||||
var __vue_script__$6 = script$6;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$5 = function() {
|
||||
var __vue_render__$6 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1351,17 +1474,17 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$5 = [];
|
||||
__vue_render__$5._withStripped = true;
|
||||
var __vue_staticRenderFns__$6 = [];
|
||||
__vue_render__$6._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$5 = undefined;
|
||||
var __vue_inject_styles__$6 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$5 = undefined;
|
||||
var __vue_scope_id__$6 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$5 = undefined;
|
||||
var __vue_module_identifier__$6 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$5 = false;
|
||||
var __vue_is_functional_template__$6 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1371,12 +1494,12 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
|
||||
|
||||
var FormulateInputSelect = normalizeComponent(
|
||||
{ render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 },
|
||||
__vue_inject_styles__$5,
|
||||
__vue_script__$5,
|
||||
__vue_scope_id__$5,
|
||||
__vue_is_functional_template__$5,
|
||||
__vue_module_identifier__$5,
|
||||
{ render: __vue_render__$6, staticRenderFns: __vue_staticRenderFns__$6 },
|
||||
__vue_inject_styles__$6,
|
||||
__vue_script__$6,
|
||||
__vue_scope_id__$6,
|
||||
__vue_is_functional_template__$6,
|
||||
__vue_module_identifier__$6,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1385,16 +1508,16 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
|
||||
//
|
||||
|
||||
var script$6 = {
|
||||
var script$7 = {
|
||||
name: 'FormulateInputTextArea',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$6 = script$6;
|
||||
var __vue_script__$7 = script$7;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$6 = function() {
|
||||
var __vue_render__$7 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1434,17 +1557,17 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$6 = [];
|
||||
__vue_render__$6._withStripped = true;
|
||||
var __vue_staticRenderFns__$7 = [];
|
||||
__vue_render__$7._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$6 = undefined;
|
||||
var __vue_inject_styles__$7 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$6 = undefined;
|
||||
var __vue_scope_id__$7 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$6 = undefined;
|
||||
var __vue_module_identifier__$7 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$6 = false;
|
||||
var __vue_is_functional_template__$7 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1454,12 +1577,12 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
|
||||
|
||||
var FormulateInputTextArea = normalizeComponent(
|
||||
{ render: __vue_render__$6, staticRenderFns: __vue_staticRenderFns__$6 },
|
||||
__vue_inject_styles__$6,
|
||||
__vue_script__$6,
|
||||
__vue_scope_id__$6,
|
||||
__vue_is_functional_template__$6,
|
||||
__vue_module_identifier__$6,
|
||||
{ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 },
|
||||
__vue_inject_styles__$7,
|
||||
__vue_script__$7,
|
||||
__vue_scope_id__$7,
|
||||
__vue_is_functional_template__$7,
|
||||
__vue_module_identifier__$7,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1474,6 +1597,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
components: {
|
||||
FormulateForm: FormulateForm,
|
||||
FormulateInput: FormulateInput,
|
||||
FormulateInputErrors: FormulateInputErrors,
|
||||
FormulateInputBox: FormulateInputBox,
|
||||
FormulateInputText: FormulateInputText,
|
||||
FormulateInputGroup: FormulateInputGroup,
|
||||
|
280
dist/formulate.umd.js
vendored
280
dist/formulate.umd.js
vendored
@ -146,6 +146,26 @@
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, object, falsey, or array - return an array.
|
||||
* @param {mixed} item
|
||||
*/
|
||||
function arrayify (item) {
|
||||
if (!item) {
|
||||
return []
|
||||
}
|
||||
if (typeof item === 'string') {
|
||||
return [item]
|
||||
}
|
||||
if (Array.isArray(item)) {
|
||||
return item
|
||||
}
|
||||
if (typeof item === 'object') {
|
||||
return Object.values(item)
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* For a single instance of an input, export all of the context needed to fully
|
||||
* render that element.
|
||||
@ -171,7 +191,8 @@
|
||||
typeContext: typeContext,
|
||||
elementAttributes: elementAttributes,
|
||||
logicalLabelPosition: logicalLabelPosition,
|
||||
isVmodeled: isVmodeled
|
||||
isVmodeled: isVmodeled,
|
||||
mergedErrors: mergedErrors
|
||||
};
|
||||
|
||||
/**
|
||||
@ -274,6 +295,16 @@
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* The merged errors computed property.
|
||||
*/
|
||||
function mergedErrors () {
|
||||
return arrayify(this.errors)
|
||||
.concat(arrayify(this.error))
|
||||
.concat(arrayify(this.validationErrors))
|
||||
.reduce(function (errors, err) { return !errors.includes(err) ? errors.concat(err) : errors; }, [])
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
@ -367,6 +398,14 @@
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
errors: {
|
||||
type: [String, Array, Boolean],
|
||||
default: false
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data: function data () {
|
||||
@ -566,8 +605,11 @@
|
||||
staticClass: "formulate-input-help",
|
||||
domProps: { textContent: _vm._s(_vm.help) }
|
||||
})
|
||||
: _vm._e()
|
||||
]
|
||||
: _vm._e(),
|
||||
_vm._v(" "),
|
||||
_c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } })
|
||||
],
|
||||
1
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__ = [];
|
||||
@ -748,6 +790,87 @@
|
||||
undefined
|
||||
);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
var script$2 = {
|
||||
props: {
|
||||
errors: {
|
||||
type: [Boolean, Array],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$2 = script$2;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$2 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
return _vm.errors.length
|
||||
? _c(
|
||||
"ul",
|
||||
{ staticClass: "formulate-input-errors" },
|
||||
_vm._l(_vm.errors, function(error) {
|
||||
return _c("li", {
|
||||
key: error,
|
||||
staticClass: "formulate-input-error",
|
||||
domProps: { innerHTML: _vm._s(error) }
|
||||
})
|
||||
}),
|
||||
0
|
||||
)
|
||||
: _vm._e()
|
||||
};
|
||||
var __vue_staticRenderFns__$2 = [];
|
||||
__vue_render__$2._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$2 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$2 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$2 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$2 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
|
||||
/* style inject shadow dom */
|
||||
|
||||
|
||||
|
||||
var FormulateInputErrors = normalizeComponent(
|
||||
{ render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
|
||||
__vue_inject_styles__$2,
|
||||
__vue_script__$2,
|
||||
__vue_scope_id__$2,
|
||||
__vue_is_functional_template__$2,
|
||||
__vue_module_identifier__$2,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
@ -763,7 +886,7 @@
|
||||
//
|
||||
|
||||
function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
|
||||
var script$2 = {
|
||||
var script$3 = {
|
||||
name: 'FormulateInputGroup',
|
||||
props: {
|
||||
context: {
|
||||
@ -801,10 +924,10 @@
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$2 = script$2;
|
||||
var __vue_script__$3 = script$3;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$2 = function() {
|
||||
var __vue_render__$3 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -836,17 +959,17 @@
|
||||
1
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$2 = [];
|
||||
__vue_render__$2._withStripped = true;
|
||||
var __vue_staticRenderFns__$3 = [];
|
||||
__vue_render__$3._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$2 = undefined;
|
||||
var __vue_inject_styles__$3 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$2 = undefined;
|
||||
var __vue_scope_id__$3 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$2 = undefined;
|
||||
var __vue_module_identifier__$3 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$2 = false;
|
||||
var __vue_is_functional_template__$3 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -856,12 +979,12 @@
|
||||
|
||||
|
||||
var FormulateInputGroup = normalizeComponent(
|
||||
{ render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
|
||||
__vue_inject_styles__$2,
|
||||
__vue_script__$2,
|
||||
__vue_scope_id__$2,
|
||||
__vue_is_functional_template__$2,
|
||||
__vue_module_identifier__$2,
|
||||
{ render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 },
|
||||
__vue_inject_styles__$3,
|
||||
__vue_script__$3,
|
||||
__vue_scope_id__$3,
|
||||
__vue_is_functional_template__$3,
|
||||
__vue_module_identifier__$3,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -896,16 +1019,16 @@
|
||||
|
||||
//
|
||||
|
||||
var script$3 = {
|
||||
var script$4 = {
|
||||
name: 'FormulateInputBox',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$3 = script$3;
|
||||
var __vue_script__$4 = script$4;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$3 = function() {
|
||||
var __vue_render__$4 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1034,17 +1157,17 @@
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$3 = [];
|
||||
__vue_render__$3._withStripped = true;
|
||||
var __vue_staticRenderFns__$4 = [];
|
||||
__vue_render__$4._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$3 = undefined;
|
||||
var __vue_inject_styles__$4 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$3 = undefined;
|
||||
var __vue_scope_id__$4 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$3 = undefined;
|
||||
var __vue_module_identifier__$4 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$3 = false;
|
||||
var __vue_is_functional_template__$4 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1054,12 +1177,12 @@
|
||||
|
||||
|
||||
var FormulateInputBox = normalizeComponent(
|
||||
{ render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 },
|
||||
__vue_inject_styles__$3,
|
||||
__vue_script__$3,
|
||||
__vue_scope_id__$3,
|
||||
__vue_is_functional_template__$3,
|
||||
__vue_module_identifier__$3,
|
||||
{ render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 },
|
||||
__vue_inject_styles__$4,
|
||||
__vue_script__$4,
|
||||
__vue_scope_id__$4,
|
||||
__vue_is_functional_template__$4,
|
||||
__vue_module_identifier__$4,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1068,16 +1191,16 @@
|
||||
|
||||
//
|
||||
|
||||
var script$4 = {
|
||||
var script$5 = {
|
||||
name: 'FormulateInputText',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$4 = script$4;
|
||||
var __vue_script__$5 = script$5;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$4 = function() {
|
||||
var __vue_render__$5 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1193,17 +1316,17 @@
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$4 = [];
|
||||
__vue_render__$4._withStripped = true;
|
||||
var __vue_staticRenderFns__$5 = [];
|
||||
__vue_render__$5._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$4 = undefined;
|
||||
var __vue_inject_styles__$5 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$4 = undefined;
|
||||
var __vue_scope_id__$5 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$4 = undefined;
|
||||
var __vue_module_identifier__$5 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$4 = false;
|
||||
var __vue_is_functional_template__$5 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1213,12 +1336,12 @@
|
||||
|
||||
|
||||
var FormulateInputText = normalizeComponent(
|
||||
{ render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 },
|
||||
__vue_inject_styles__$4,
|
||||
__vue_script__$4,
|
||||
__vue_scope_id__$4,
|
||||
__vue_is_functional_template__$4,
|
||||
__vue_module_identifier__$4,
|
||||
{ render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 },
|
||||
__vue_inject_styles__$5,
|
||||
__vue_script__$5,
|
||||
__vue_scope_id__$5,
|
||||
__vue_is_functional_template__$5,
|
||||
__vue_module_identifier__$5,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1227,7 +1350,7 @@
|
||||
|
||||
//
|
||||
|
||||
var script$5 = {
|
||||
var script$6 = {
|
||||
name: 'FormulateInputSelect',
|
||||
mixins: [FormulateInputMixin],
|
||||
computed: {
|
||||
@ -1244,10 +1367,10 @@
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$5 = script$5;
|
||||
var __vue_script__$6 = script$6;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$5 = function() {
|
||||
var __vue_render__$6 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1354,17 +1477,17 @@
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$5 = [];
|
||||
__vue_render__$5._withStripped = true;
|
||||
var __vue_staticRenderFns__$6 = [];
|
||||
__vue_render__$6._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$5 = undefined;
|
||||
var __vue_inject_styles__$6 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$5 = undefined;
|
||||
var __vue_scope_id__$6 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$5 = undefined;
|
||||
var __vue_module_identifier__$6 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$5 = false;
|
||||
var __vue_is_functional_template__$6 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1374,12 +1497,12 @@
|
||||
|
||||
|
||||
var FormulateInputSelect = normalizeComponent(
|
||||
{ render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 },
|
||||
__vue_inject_styles__$5,
|
||||
__vue_script__$5,
|
||||
__vue_scope_id__$5,
|
||||
__vue_is_functional_template__$5,
|
||||
__vue_module_identifier__$5,
|
||||
{ render: __vue_render__$6, staticRenderFns: __vue_staticRenderFns__$6 },
|
||||
__vue_inject_styles__$6,
|
||||
__vue_script__$6,
|
||||
__vue_scope_id__$6,
|
||||
__vue_is_functional_template__$6,
|
||||
__vue_module_identifier__$6,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1388,16 +1511,16 @@
|
||||
|
||||
//
|
||||
|
||||
var script$6 = {
|
||||
var script$7 = {
|
||||
name: 'FormulateInputTextArea',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$6 = script$6;
|
||||
var __vue_script__$7 = script$7;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$6 = function() {
|
||||
var __vue_render__$7 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
@ -1437,17 +1560,17 @@
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$6 = [];
|
||||
__vue_render__$6._withStripped = true;
|
||||
var __vue_staticRenderFns__$7 = [];
|
||||
__vue_render__$7._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$6 = undefined;
|
||||
var __vue_inject_styles__$7 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$6 = undefined;
|
||||
var __vue_scope_id__$7 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$6 = undefined;
|
||||
var __vue_module_identifier__$7 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$6 = false;
|
||||
var __vue_is_functional_template__$7 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -1457,12 +1580,12 @@
|
||||
|
||||
|
||||
var FormulateInputTextArea = normalizeComponent(
|
||||
{ render: __vue_render__$6, staticRenderFns: __vue_staticRenderFns__$6 },
|
||||
__vue_inject_styles__$6,
|
||||
__vue_script__$6,
|
||||
__vue_scope_id__$6,
|
||||
__vue_is_functional_template__$6,
|
||||
__vue_module_identifier__$6,
|
||||
{ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 },
|
||||
__vue_inject_styles__$7,
|
||||
__vue_script__$7,
|
||||
__vue_scope_id__$7,
|
||||
__vue_is_functional_template__$7,
|
||||
__vue_module_identifier__$7,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -1477,6 +1600,7 @@
|
||||
components: {
|
||||
FormulateForm: FormulateForm,
|
||||
FormulateInput: FormulateInput,
|
||||
FormulateInputErrors: FormulateInputErrors,
|
||||
FormulateInputBox: FormulateInputBox,
|
||||
FormulateInputText: FormulateInputText,
|
||||
FormulateInputGroup: FormulateInputGroup,
|
||||
|
10
dist/snow.css
vendored
10
dist/snow.css
vendored
@ -15,6 +15,16 @@
|
||||
font-weight: 300;
|
||||
line-height: 1.5;
|
||||
margin-bottom: .25em; }
|
||||
.formulate-input .formulate-input-errors {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0; }
|
||||
.formulate-input .formulate-input-error {
|
||||
color: #960505;
|
||||
font-size: .8em;
|
||||
font-weight: 300;
|
||||
line-height: 1.5;
|
||||
margin-bottom: .25em; }
|
||||
.formulate-input .formulate-input-group-item {
|
||||
margin-bottom: .5em; }
|
||||
.formulate-input:last-child {
|
||||
|
4
dist/snow.min.css
vendored
4
dist/snow.min.css
vendored
File diff suppressed because one or more lines are too long
@ -2,6 +2,7 @@ import library from './libs/library'
|
||||
import isPlainObject from 'is-plain-object'
|
||||
import FormulateInput from './FormulateInput.vue'
|
||||
import FormulateForm from './FormulateForm.vue'
|
||||
import FormulateInputErrors from './FormulateInputErrors.vue'
|
||||
import FormulateInputGroup from './FormulateInputGroup.vue'
|
||||
import FormulateInputBox from './inputs/FormulateInputBox.vue'
|
||||
import FormulateInputText from './inputs/FormulateInputText.vue'
|
||||
@ -19,6 +20,7 @@ class Formulate {
|
||||
components: {
|
||||
FormulateForm,
|
||||
FormulateInput,
|
||||
FormulateInputErrors,
|
||||
FormulateInputBox,
|
||||
FormulateInputText,
|
||||
FormulateInputGroup,
|
||||
|
@ -2,6 +2,7 @@
|
||||
<div
|
||||
class="formulate-input"
|
||||
:data-classification="classification"
|
||||
:data-has-errors="hasErrors"
|
||||
:data-type="type"
|
||||
>
|
||||
<div class="formulate-input-wrapper">
|
||||
@ -39,6 +40,9 @@
|
||||
class="formulate-input-help"
|
||||
v-text="help"
|
||||
/>
|
||||
<FormulateInputErrors
|
||||
:errors="mergedErrors"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -102,6 +106,25 @@ export default {
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
errors: {
|
||||
type: [String, Array, Boolean],
|
||||
default: false
|
||||
},
|
||||
validation: {
|
||||
type: [String, Boolean, Array],
|
||||
default: false
|
||||
},
|
||||
validationBehavior: {
|
||||
type: String,
|
||||
default: 'blur',
|
||||
validator: function (value) {
|
||||
return ['blur', 'live'].includes(value)
|
||||
}
|
||||
},
|
||||
error: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
|
26
src/FormulateInputErrors.vue
Normal file
26
src/FormulateInputErrors.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<ul
|
||||
v-if="errors.length"
|
||||
class="formulate-input-errors"
|
||||
>
|
||||
<!-- eslint-disable -->
|
||||
<li
|
||||
v-for="error in errors"
|
||||
:key="error"
|
||||
v-html="error"
|
||||
class="formulate-input-error"
|
||||
/>
|
||||
<!-- eslint-enable -->
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
errors: {
|
||||
type: [Boolean, Array],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,5 +1,5 @@
|
||||
import nanoid from 'nanoid'
|
||||
import { map } from './utils'
|
||||
import { map, arrayify, parseRules } from './utils'
|
||||
|
||||
/**
|
||||
* For a single instance of an input, export all of the context needed to fully
|
||||
@ -28,7 +28,10 @@ export default {
|
||||
typeContext,
|
||||
elementAttributes,
|
||||
logicalLabelPosition,
|
||||
isVmodeled
|
||||
isVmodeled,
|
||||
mergedErrors,
|
||||
hasErrors,
|
||||
validationRules
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,6 +132,30 @@ function createOptionList (options) {
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* The merged errors computed property.
|
||||
*/
|
||||
function mergedErrors () {
|
||||
return arrayify(this.errors)
|
||||
.concat(arrayify(this.error))
|
||||
.concat(arrayify(this.validationErrors))
|
||||
.reduce((errors, err) => !errors.includes(err) ? errors.concat(err) : errors, [])
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this computed property have errors.
|
||||
*/
|
||||
function hasErrors () {
|
||||
return !!this.mergedErrors.length
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of validation rules to pass.
|
||||
*/
|
||||
function validationRules () {
|
||||
return parseRules(this.validation)
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
|
41
src/libs/rules.js
Normal file
41
src/libs/rules.js
Normal file
@ -0,0 +1,41 @@
|
||||
import { shallowEqualObjects } from './utils'
|
||||
|
||||
/**
|
||||
* Library of rules
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Rule: must be a value
|
||||
*/
|
||||
required: async function (value) {
|
||||
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: async function (value, ...stack) {
|
||||
return !!stack.find(item => shallowEqualObjects(item, value))
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: Match the value against a (stack) of patterns or strings
|
||||
*/
|
||||
matches: async function (value, ...stack) {
|
||||
return !!stack.find(pattern => {
|
||||
if (pattern instanceof RegExp) {
|
||||
return pattern.test(value)
|
||||
}
|
||||
return pattern === value
|
||||
})
|
||||
}
|
||||
}
|
@ -69,3 +69,68 @@ export function shallowEqualObjects (objA, objB) {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, object, falsey, or array - return an array.
|
||||
* @param {mixed} item
|
||||
*/
|
||||
export function arrayify (item) {
|
||||
if (!item) {
|
||||
return []
|
||||
}
|
||||
if (typeof item === 'string') {
|
||||
return [item]
|
||||
}
|
||||
if (Array.isArray(item)) {
|
||||
return item
|
||||
}
|
||||
if (typeof item === 'object') {
|
||||
return Object.values(item)
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array or string return an array of callables.
|
||||
* @param {array|string} validation
|
||||
* @param {array} rules and array of functions
|
||||
* @return {array} an array of functions
|
||||
*/
|
||||
export function parseRules (validation, rules) {
|
||||
if (typeof validation === 'string') {
|
||||
return parseRules(validation.split('|'), rules)
|
||||
}
|
||||
if (!Array.isArray(validation)) {
|
||||
return []
|
||||
}
|
||||
return validation.map(rule => parseRule(rule, rules)).filter(f => !!f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string or function, parse it and return the an array in the format
|
||||
* [fn, [...arguments]]
|
||||
* @param {string|function} rule
|
||||
*/
|
||||
function parseRule (rule, rules) {
|
||||
if (typeof rule === 'function') {
|
||||
return [rule, []]
|
||||
}
|
||||
if (Array.isArray(rule) && rule.length) {
|
||||
if (typeof rule[0] === 'string' && rules.hasOwnProperty(rule[0])) {
|
||||
return [rules[rule.shift()], rule]
|
||||
}
|
||||
if (typeof rule[0] === 'function') {
|
||||
return [rule.shift(), rule]
|
||||
}
|
||||
}
|
||||
if (typeof rule === 'string') {
|
||||
const segments = rule.split(':')
|
||||
const functionName = segments.shift()
|
||||
if (rules.hasOwnProperty(functionName)) {
|
||||
return [rules[functionName], segments.length ? segments.join(':').split(',') : []]
|
||||
} else {
|
||||
throw new Error(`Unknown validation rule ${rule}`)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ test('installs on vue instance', () => {
|
||||
const components = [
|
||||
'FormulateForm',
|
||||
'FormulateInput',
|
||||
'FormulateInputErrors',
|
||||
'FormulateInputBox',
|
||||
'FormulateInputText',
|
||||
'FormulateInputGroup',
|
||||
|
@ -11,145 +11,176 @@ Vue.use(Formulate)
|
||||
* Test each type of text element
|
||||
*/
|
||||
|
||||
test('type "text" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "search" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'search' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "email" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'email' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "number" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'number' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "color" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'color' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "date" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'date' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "month" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'month' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "password" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'password' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "range" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'range' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "tel" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'tel' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "time" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'time' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "url" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'url' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('type "week" renders a text input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'week' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
/**
|
||||
* Test rendering functionality to text inputs
|
||||
*/
|
||||
|
||||
test('text inputs automatically have id assigned', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
expect(wrapper.vm.context).toHaveProperty('id')
|
||||
expect(wrapper.find(`input[id="${wrapper.vm.context.attributes.id}"]`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
test('text inputs dont have labels', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
expect(wrapper.find('label').exists()).toBe(false)
|
||||
})
|
||||
|
||||
test('text inputs can have labels', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', label: 'Field label' } })
|
||||
expect(wrapper.find(`label[for="${wrapper.vm.context.attributes.id}"]`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
test('text inputs dont have help text', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
expect(wrapper.find(`.formulate-input-help`).exists()).toBe(false)
|
||||
})
|
||||
|
||||
test('text inputs dont have help text', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', help: 'This is some help text' } })
|
||||
expect(wrapper.find(`.formulate-input-help`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
/**
|
||||
* Test data binding
|
||||
*/
|
||||
test('text inputs emit input (vmodel) event with value when edited', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
wrapper.find('input').setValue('Updated Value')
|
||||
expect(wrapper.emitted().input).toBeTruthy()
|
||||
expect(wrapper.emitted().input[0]).toEqual(['Updated Value'])
|
||||
})
|
||||
|
||||
|
||||
test('test that inputs that arent updated dont re-context themselves', () => {
|
||||
const wrapper = mount({
|
||||
data () {
|
||||
return {
|
||||
valueA: 'first value',
|
||||
valueB: 'second value'
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<FormulateInput type="text" ref="first" v-model="valueA" :placeholder="valueA" />
|
||||
<FormulateInput type="text" ref="second" v-model="valueB" :placeholder="valueB" />
|
||||
</div>
|
||||
`
|
||||
describe('FormulateInputText', () => {
|
||||
it('renders text input when type is "text"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
const firstContext = wrapper.find({ref: "first"}).vm.context
|
||||
const secondContext = wrapper.find({ref: "second"}).vm.context
|
||||
wrapper.find('input').setValue('new value')
|
||||
expect(firstContext).toBeTruthy()
|
||||
expect(wrapper.vm.valueA === 'new value').toBe(true)
|
||||
expect(wrapper.vm.valueB === 'second value').toBe(true)
|
||||
expect(wrapper.find({ref: "first"}).vm.context === firstContext).toBe(false)
|
||||
expect(wrapper.find({ref: "second"}).vm.context === secondContext).toBe(true)
|
||||
})
|
||||
|
||||
test('test that inputs contain their v-model value as the initial input', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', formulateValue: 'initial val' } })
|
||||
expect(wrapper.find('input').element.value).toBe('initial val')
|
||||
})
|
||||
it('renders search input when type is "search"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'search' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
test('test that inputs without v-model set a proxy model', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'textarea' } })
|
||||
const input = wrapper.find('textarea')
|
||||
input.setValue('changed value')
|
||||
expect(wrapper.vm.internalModelProxy).toBe('changed value')
|
||||
it('renders email input when type is "email"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'email' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders number input when type is "number"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'number' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders color input when type is "color"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'color' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders date input when type is "date"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'date' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders month input when type is "month"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'month' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders password input when type is "password"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'password' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders range input when type is "range"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'range' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders tel input when type is "tel"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'tel' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders time input when type is "time"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'time' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders url input when type is "url"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'url' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders week input when type is "week"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'week' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
/**
|
||||
* Test rendering functionality to text inputs
|
||||
*/
|
||||
|
||||
it('automatically assigns an id', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
expect(wrapper.vm.context).toHaveProperty('id')
|
||||
expect(wrapper.find(`input[id="${wrapper.vm.context.attributes.id}"]`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('doesn’t automatically add a label', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
expect(wrapper.find('label').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('renders labels', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', label: 'Field label' } })
|
||||
expect(wrapper.find(`label[for="${wrapper.vm.context.attributes.id}"]`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('doesn’t automatically render help text', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
expect(wrapper.find(`.formulate-input-help`).exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('renders help text', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', help: 'This is some help text' } })
|
||||
expect(wrapper.find(`.formulate-input-help`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
/**
|
||||
* Test data binding
|
||||
*/
|
||||
it('emits input (vmodel) event with value when edited', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
wrapper.find('input').setValue('Updated Value')
|
||||
expect(wrapper.emitted().input).toBeTruthy()
|
||||
expect(wrapper.emitted().input[0]).toEqual(['Updated Value'])
|
||||
})
|
||||
|
||||
|
||||
it('doesn’t re-context itself if there were no changes', () => {
|
||||
const wrapper = mount({
|
||||
data () {
|
||||
return {
|
||||
valueA: 'first value',
|
||||
valueB: 'second value'
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<FormulateInput type="text" ref="first" v-model="valueA" :placeholder="valueA" />
|
||||
<FormulateInput type="text" ref="second" v-model="valueB" :placeholder="valueB" />
|
||||
</div>
|
||||
`
|
||||
})
|
||||
const firstContext = wrapper.find({ref: "first"}).vm.context
|
||||
const secondContext = wrapper.find({ref: "second"}).vm.context
|
||||
wrapper.find('input').setValue('new value')
|
||||
expect(firstContext).toBeTruthy()
|
||||
expect(wrapper.vm.valueA === 'new value').toBe(true)
|
||||
expect(wrapper.vm.valueB === 'second value').toBe(true)
|
||||
expect(wrapper.find({ref: "first"}).vm.context === firstContext).toBe(false)
|
||||
expect(wrapper.find({ref: "second"}).vm.context === secondContext).toBe(true)
|
||||
})
|
||||
|
||||
it('uses the v-model value as the initial value', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', formulateValue: 'initial val' } })
|
||||
expect(wrapper.find('input').element.value).toBe('initial val')
|
||||
})
|
||||
|
||||
it('uses a proxy model internally if it doesnt have a v-model', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'textarea' } })
|
||||
const input = wrapper.find('textarea')
|
||||
input.setValue('changed value')
|
||||
expect(wrapper.vm.internalModelProxy).toBe('changed value')
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Test error handling
|
||||
*/
|
||||
it('doesn’t automatically render errors', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text' } })
|
||||
expect(wrapper.find('.formulate-input-errors').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('accepts a single string as an error prop', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', 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'] } })
|
||||
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'] } })
|
||||
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'] } })
|
||||
expect(wrapper.find('[data-has-errors]').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
77
test/rules.test.js
Normal file
77
test/rules.test.js
Normal file
@ -0,0 +1,77 @@
|
||||
import rules from '@/libs/rules'
|
||||
|
||||
/**
|
||||
* Required rule
|
||||
*/
|
||||
describe('required', () => {
|
||||
it('fails on empty string', async () => expect(await rules.required('')).toBe(false))
|
||||
|
||||
it('fails on empty array', async () => expect(await rules.required([])).toBe(false))
|
||||
|
||||
it('fails on empty object', async () => expect(await rules.required({})).toBe(false))
|
||||
|
||||
it('fails on null', async () => expect(await rules.required(null)).toBe(false))
|
||||
|
||||
it('passes with the number zero', async () => expect(await rules.required(0)).toBe(true))
|
||||
|
||||
it('passes with the boolean false', async () => expect(await rules.required(false)).toBe(true))
|
||||
|
||||
it('passes with a non empty array', async () => expect(await rules.required(['123'])).toBe(true))
|
||||
|
||||
it('passes with a non empty object', async () => expect(await rules.required({a: 'b'})).toBe(true))
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* In rule
|
||||
*/
|
||||
describe('in', () => {
|
||||
it('fails when not in stack', async () => {
|
||||
expect(await rules.in('third', 'first', 'second')).toBe(false)
|
||||
})
|
||||
|
||||
it('fails when case sensitive mismatch is in stack', async () => {
|
||||
expect(await rules.in('third', 'first', 'second', 'Third')).toBe(false)
|
||||
})
|
||||
|
||||
it('fails comparing dissimilar objects', async () => {
|
||||
expect(await rules.in({f: 'abc'}, {a: 'cdf'}, {b: 'abc'})).toBe(false)
|
||||
})
|
||||
|
||||
it('passes when case sensitive match is in stack', async () => {
|
||||
expect(await rules.in('third', 'first', 'second', 'third')).toBe(true)
|
||||
})
|
||||
|
||||
it('passes a shallow array compare', async () => {
|
||||
expect(await rules.in(['abc'], ['cdf'], ['abc'])).toBe(true)
|
||||
})
|
||||
|
||||
it('passes a shallow object compare', async () => {
|
||||
expect(await rules.in({f: 'abc'}, {a: 'cdf'}, {f: 'abc'},)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Matches rule
|
||||
*/
|
||||
describe('matches', () => {
|
||||
it('simple strings fail if they aren’t equal', async () => {
|
||||
expect(await rules.matches('third', 'first')).toBe(false)
|
||||
})
|
||||
|
||||
it('fails on non matching regex', async () => {
|
||||
expect(await rules.matches('third', /^thirds/)).toBe(false)
|
||||
})
|
||||
|
||||
it('passes if simple strings match', async () => {
|
||||
expect(await rules.matches('second', 'third', 'second')).toBe(true)
|
||||
})
|
||||
|
||||
it('passes on matching regex', async () => {
|
||||
expect(await rules.matches('third', /^third/)).toBe(true)
|
||||
})
|
||||
|
||||
it('passes on matching mixed regex and string', async () => {
|
||||
expect(await rules.matches('first-fourth', 'second', /^third/, /fourth$/)).toBe(true)
|
||||
})
|
||||
})
|
44
test/utils.test.js
Normal file
44
test/utils.test.js
Normal file
@ -0,0 +1,44 @@
|
||||
import { parseRules } from '@/libs/utils'
|
||||
import rules from '@/libs/rules'
|
||||
|
||||
describe('parseRules', () => {
|
||||
it('parses single string rules, returning empty arguments array', () => {
|
||||
expect(parseRules('required', rules)).toEqual([
|
||||
[rules.required, []]
|
||||
])
|
||||
})
|
||||
|
||||
it('throws errors for invalid validation rules', () => {
|
||||
expect(() => {
|
||||
parseRules('required|notarule', rules)
|
||||
}).toThrow()
|
||||
})
|
||||
|
||||
it('parses arguments for a rule', () => {
|
||||
expect(parseRules('in:foo,bar', rules)).toEqual([
|
||||
[rules.in, ['foo', 'bar']]
|
||||
])
|
||||
})
|
||||
|
||||
it('parses multiple string rules and arguments', () => {
|
||||
expect(parseRules('required|in:foo,bar', rules)).toEqual([
|
||||
[rules.required, []],
|
||||
[rules.in, ['foo', 'bar']]
|
||||
])
|
||||
})
|
||||
|
||||
it('parses multiple array rules and arguments', () => {
|
||||
expect(parseRules(['required', 'in:foo,bar'], rules)).toEqual([
|
||||
[rules.required, []],
|
||||
[rules.in, ['foo', 'bar']]
|
||||
])
|
||||
})
|
||||
|
||||
it('parses array rules with expression arguments', () => {
|
||||
expect(parseRules([
|
||||
['matches', /^abc/, '1234']
|
||||
], rules)).toEqual([
|
||||
[rules.matches, [/^abc/, '1234']]
|
||||
])
|
||||
})
|
||||
})
|
@ -25,6 +25,20 @@
|
||||
margin-bottom: .25em;
|
||||
}
|
||||
|
||||
.formulate-input-errors {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.formulate-input-error {
|
||||
color: $formulate-error;
|
||||
font-size: .8em;
|
||||
font-weight: 300;
|
||||
line-height: 1.5;
|
||||
margin-bottom: .25em;
|
||||
}
|
||||
|
||||
.formulate-input-group-item {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ $formulate-blue-l: #f3f4f4;
|
||||
|
||||
$formulate-green: #41b883;
|
||||
|
||||
$formulate-error: #960505;
|
||||
|
||||
$formulate-yellow-d: #6b5900;
|
||||
$formulate-yellow: #e6c000;
|
||||
$formulate-yellow-l: #fff8d2;
|
||||
|
Loading…
Reference in New Issue
Block a user