Adds full multi-option support for checkboxes and radios
This commit is contained in:
parent
27bd2bda26
commit
3ad166ac90
@ -19,6 +19,8 @@ export default {
|
||||
css: true, // Dynamically inject css as a <style> tag
|
||||
compileTemplate: true // Explicitly convert template to render function
|
||||
}),
|
||||
buble() // Transpile to ES5
|
||||
buble({
|
||||
objectAssign: 'Object.assign'
|
||||
}) // Transpile to ES5
|
||||
]
|
||||
}
|
||||
|
165
dist/formulate.esm.js
vendored
165
dist/formulate.esm.js
vendored
@ -111,16 +111,33 @@ function map (original, callback) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to reduce an object's properties
|
||||
* @param {Object} original
|
||||
* @param {Function} callback
|
||||
* @param {*} accumulator
|
||||
* Shallow equal.
|
||||
* @param {} objA
|
||||
* @param {*} objB
|
||||
*/
|
||||
function reduce (original, callback, accumulator) {
|
||||
for (var key in original) {
|
||||
accumulator = callback(accumulator, key, original[key]);
|
||||
function shallowEqualObjects (objA, objB) {
|
||||
if (objA === objB) {
|
||||
return true
|
||||
}
|
||||
return accumulator
|
||||
if (!objA || !objB) {
|
||||
return false
|
||||
}
|
||||
var aKeys = Object.keys(objA);
|
||||
var bKeys = Object.keys(objB);
|
||||
var len = aKeys.length;
|
||||
|
||||
if (bKeys.length !== len) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
var key = aKeys[i];
|
||||
|
||||
if (objA[key] !== objB[key]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,36 +145,45 @@ function reduce (original, callback, accumulator) {
|
||||
* render that element.
|
||||
* @return {object}
|
||||
*/
|
||||
function context () {
|
||||
return defineModel.call(this, Object.assign({
|
||||
type: this.type,
|
||||
value: this.value,
|
||||
classification: this.classification,
|
||||
component: this.component,
|
||||
id: this.id,
|
||||
label: this.label,
|
||||
labelPosition: labelPosition.call(this),
|
||||
attributes: attributeReducer.call(this, this.$attrs)
|
||||
}, typeContext.call(this)))
|
||||
}
|
||||
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,
|
||||
classification: this.classification,
|
||||
component: this.component,
|
||||
id: this.id || this.defaultId,
|
||||
label: this.label,
|
||||
labelPosition: this.logicalLabelPosition,
|
||||
attributes: this.elementAttributes},
|
||||
this.typeContext))
|
||||
},
|
||||
typeContext: typeContext,
|
||||
elementAttributes: elementAttributes,
|
||||
logicalLabelPosition: logicalLabelPosition
|
||||
};
|
||||
|
||||
/**
|
||||
* Given (this.type), return an object to merge with the context
|
||||
* @return {object}
|
||||
* @return {object}
|
||||
*/
|
||||
function typeContext () {
|
||||
var this$1 = this;
|
||||
|
||||
switch (this.classification) {
|
||||
case 'select':
|
||||
return {
|
||||
options: createOptionList(this.options),
|
||||
optionGroups: this.optionGroups ? map(this.optionGroups, function (k, v) { return createOptionList(v); }) : false,
|
||||
options: createOptionList.call(this, this.options),
|
||||
optionGroups: this.optionGroups ? map(this.optionGroups, function (k, v) { return createOptionList.call(this$1, v); }) : false,
|
||||
placeholder: this.$attrs.placeholder || false
|
||||
}
|
||||
case 'group':
|
||||
if (this.options) {
|
||||
return {
|
||||
options: createOptionList(this.options),
|
||||
component: 'FormulateInputGroup'
|
||||
options: createOptionList.call(this, this.options)
|
||||
}
|
||||
}
|
||||
break
|
||||
@ -170,20 +196,21 @@ function typeContext () {
|
||||
* Reducer for attributes that will be applied to each core input element.
|
||||
* @return {object}
|
||||
*/
|
||||
function attributeReducer (attributes) {
|
||||
if ( attributes === void 0 ) attributes = {};
|
||||
|
||||
function elementAttributes () {
|
||||
var attrs = Object.assign({}, this.localAttributes);
|
||||
if (this.id) {
|
||||
attributes.id = this.id;
|
||||
attrs.id = this.id;
|
||||
} else {
|
||||
attrs.id = this.defaultId;
|
||||
}
|
||||
return attributes
|
||||
return attrs
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the a best-guess location for the label (before or after).
|
||||
* @return {string} before|after
|
||||
*/
|
||||
function labelPosition () {
|
||||
function logicalLabelPosition () {
|
||||
if (this.labelPosition) {
|
||||
return this.labelPosition
|
||||
}
|
||||
@ -202,17 +229,22 @@ function labelPosition () {
|
||||
* @return {array}
|
||||
*/
|
||||
function createOptionList (options) {
|
||||
if (!Array.isArray(options)) {
|
||||
return reduce(options, function (options, value, label) { return options.concat({ value: value, label: label, id: nanoid(15) }); }, [])
|
||||
if (!Array.isArray(options) && options && typeof options === 'object') {
|
||||
var optionList = [];
|
||||
var that = this;
|
||||
for (var value in options) {
|
||||
optionList.push({ value: value, label: options[value], id: ((that.elementAttributes.id) + "_" + value) });
|
||||
}
|
||||
return optionList
|
||||
} else if (Array.isArray(options) && !options.length) {
|
||||
return [{ value: this.name, label: (this.label || this.name), id: nanoid(15) }]
|
||||
return [{ value: this.value, label: (this.label || this.name), id: this.context.id || nanoid(9) }]
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a getter/setter model factory
|
||||
* @return object
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
*/
|
||||
function defineModel (context) {
|
||||
return Object.defineProperty(context, 'model', {
|
||||
@ -257,7 +289,7 @@ var script = {
|
||||
},
|
||||
formulateValue: {
|
||||
type: [String, Number, Object, Boolean, Array],
|
||||
default: false
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: [String, Number, Object, Boolean, Array],
|
||||
@ -273,7 +305,7 @@ var script = {
|
||||
},
|
||||
id: {
|
||||
type: [String, Boolean, Number],
|
||||
default: function () { return nanoid(9); }
|
||||
default: false
|
||||
},
|
||||
label: {
|
||||
type: [String, Boolean],
|
||||
@ -286,16 +318,47 @@ var script = {
|
||||
help: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
context: context,
|
||||
classification: function classification () {
|
||||
data: function data () {
|
||||
return {
|
||||
defaultId: nanoid(9),
|
||||
localAttributes: {}
|
||||
}
|
||||
},
|
||||
computed: Object.assign({}, context,
|
||||
{classification: function classification () {
|
||||
var classification = this.$formulate.classify(this.type);
|
||||
return (classification === 'box' && this.options) ? 'group' : classification
|
||||
},
|
||||
component: function component () {
|
||||
return this.$formulate.component(this.type)
|
||||
return (this.classification === 'group') ? 'FormulateInputGroup' : this.$formulate.component(this.type)
|
||||
}}),
|
||||
watch: {
|
||||
'$attrs': {
|
||||
handler: function handler (value) {
|
||||
this.updateLocalAttributes(value);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
created: function created () {
|
||||
this.updateLocalAttributes(this.$attrs);
|
||||
},
|
||||
mounted: function mounted () {
|
||||
if (this.debug) {
|
||||
console.log('MOUNTED:' + this.$options.name + ':' + this.type);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateLocalAttributes: function updateLocalAttributes (value) {
|
||||
if (!shallowEqualObjects(value, this.localAttributes)) {
|
||||
this.localAttributes = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -414,7 +477,7 @@ var __vue_render__ = function() {
|
||||
_c("label", {
|
||||
staticClass:
|
||||
"formulate-input-label formulate-input-label--before",
|
||||
attrs: { for: _vm.id },
|
||||
attrs: { for: _vm.context.attributes.id },
|
||||
domProps: { textContent: _vm._s(_vm.context.label) }
|
||||
})
|
||||
],
|
||||
@ -442,7 +505,7 @@ var __vue_render__ = function() {
|
||||
_c("label", {
|
||||
staticClass:
|
||||
"formulate-input-label formulate-input-label--after",
|
||||
attrs: { for: _vm.id },
|
||||
attrs: { for: _vm.context.attributes.id },
|
||||
domProps: { textContent: _vm._s(_vm.context.label) }
|
||||
})
|
||||
],
|
||||
@ -562,7 +625,8 @@ var script$1 = {
|
||||
var options = ref.options;
|
||||
var labelPosition = ref.labelPosition;
|
||||
var attributes = ref.attributes;
|
||||
var rest = objectWithoutProperties( ref, ["options", "labelPosition", "attributes"] );
|
||||
var classification = ref.classification;
|
||||
var rest = objectWithoutProperties( ref, ["options", "labelPosition", "attributes", "classification"] );
|
||||
var context = rest;
|
||||
return this.options.map(function (option) { return this$1.groupItemContext(context, option); })
|
||||
}
|
||||
@ -647,10 +711,18 @@ __vue_render__$2._withStripped = true;
|
||||
* Default base for input components.
|
||||
*/
|
||||
var FormulateInputMixin = {
|
||||
model: {
|
||||
prop: 'formulateValue',
|
||||
event: 'input'
|
||||
},
|
||||
props: {
|
||||
context: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
formulateValue: {
|
||||
type: [Object, Array, Boolean, String, Number],
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -664,7 +736,7 @@ var FormulateInputMixin = {
|
||||
return this.context.attributes || {}
|
||||
},
|
||||
hasValue: function hasValue () {
|
||||
return !!this.context.model
|
||||
return !!this.model
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1005,7 +1077,7 @@ var script$4 = {
|
||||
return this.context.optionGroups || false
|
||||
},
|
||||
placeholderSelected: function placeholderSelected () {
|
||||
return !!(!this.hasValue && this.context.attributes.placeholder)
|
||||
return !!(!this.hasValue && this.context.attributes && this.context.attributes.placeholder)
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1255,6 +1327,7 @@ Formulate.prototype.install = function install (Vue, options) {
|
||||
for (var componentName in this.options.components) {
|
||||
Vue.component(componentName, this.options.components[componentName]);
|
||||
}
|
||||
Object.freeze(this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
165
dist/formulate.min.js
vendored
165
dist/formulate.min.js
vendored
@ -114,16 +114,33 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to reduce an object's properties
|
||||
* @param {Object} original
|
||||
* @param {Function} callback
|
||||
* @param {*} accumulator
|
||||
* Shallow equal.
|
||||
* @param {} objA
|
||||
* @param {*} objB
|
||||
*/
|
||||
function reduce (original, callback, accumulator) {
|
||||
for (var key in original) {
|
||||
accumulator = callback(accumulator, key, original[key]);
|
||||
function shallowEqualObjects (objA, objB) {
|
||||
if (objA === objB) {
|
||||
return true
|
||||
}
|
||||
return accumulator
|
||||
if (!objA || !objB) {
|
||||
return false
|
||||
}
|
||||
var aKeys = Object.keys(objA);
|
||||
var bKeys = Object.keys(objB);
|
||||
var len = aKeys.length;
|
||||
|
||||
if (bKeys.length !== len) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
var key = aKeys[i];
|
||||
|
||||
if (objA[key] !== objB[key]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,36 +148,45 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
* render that element.
|
||||
* @return {object}
|
||||
*/
|
||||
function context () {
|
||||
return defineModel.call(this, Object.assign({
|
||||
type: this.type,
|
||||
value: this.value,
|
||||
classification: this.classification,
|
||||
component: this.component,
|
||||
id: this.id,
|
||||
label: this.label,
|
||||
labelPosition: labelPosition.call(this),
|
||||
attributes: attributeReducer.call(this, this.$attrs)
|
||||
}, typeContext.call(this)))
|
||||
}
|
||||
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,
|
||||
classification: this.classification,
|
||||
component: this.component,
|
||||
id: this.id || this.defaultId,
|
||||
label: this.label,
|
||||
labelPosition: this.logicalLabelPosition,
|
||||
attributes: this.elementAttributes},
|
||||
this.typeContext))
|
||||
},
|
||||
typeContext: typeContext,
|
||||
elementAttributes: elementAttributes,
|
||||
logicalLabelPosition: logicalLabelPosition
|
||||
};
|
||||
|
||||
/**
|
||||
* Given (this.type), return an object to merge with the context
|
||||
* @return {object}
|
||||
* @return {object}
|
||||
*/
|
||||
function typeContext () {
|
||||
var this$1 = this;
|
||||
|
||||
switch (this.classification) {
|
||||
case 'select':
|
||||
return {
|
||||
options: createOptionList(this.options),
|
||||
optionGroups: this.optionGroups ? map(this.optionGroups, function (k, v) { return createOptionList(v); }) : false,
|
||||
options: createOptionList.call(this, this.options),
|
||||
optionGroups: this.optionGroups ? map(this.optionGroups, function (k, v) { return createOptionList.call(this$1, v); }) : false,
|
||||
placeholder: this.$attrs.placeholder || false
|
||||
}
|
||||
case 'group':
|
||||
if (this.options) {
|
||||
return {
|
||||
options: createOptionList(this.options),
|
||||
component: 'FormulateInputGroup'
|
||||
options: createOptionList.call(this, this.options)
|
||||
}
|
||||
}
|
||||
break
|
||||
@ -173,20 +199,21 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
* Reducer for attributes that will be applied to each core input element.
|
||||
* @return {object}
|
||||
*/
|
||||
function attributeReducer (attributes) {
|
||||
if ( attributes === void 0 ) attributes = {};
|
||||
|
||||
function elementAttributes () {
|
||||
var attrs = Object.assign({}, this.localAttributes);
|
||||
if (this.id) {
|
||||
attributes.id = this.id;
|
||||
attrs.id = this.id;
|
||||
} else {
|
||||
attrs.id = this.defaultId;
|
||||
}
|
||||
return attributes
|
||||
return attrs
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the a best-guess location for the label (before or after).
|
||||
* @return {string} before|after
|
||||
*/
|
||||
function labelPosition () {
|
||||
function logicalLabelPosition () {
|
||||
if (this.labelPosition) {
|
||||
return this.labelPosition
|
||||
}
|
||||
@ -205,17 +232,22 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
* @return {array}
|
||||
*/
|
||||
function createOptionList (options) {
|
||||
if (!Array.isArray(options)) {
|
||||
return reduce(options, function (options, value, label) { return options.concat({ value: value, label: label, id: nanoid(15) }); }, [])
|
||||
if (!Array.isArray(options) && options && typeof options === 'object') {
|
||||
var optionList = [];
|
||||
var that = this;
|
||||
for (var value in options) {
|
||||
optionList.push({ value: value, label: options[value], id: ((that.elementAttributes.id) + "_" + value) });
|
||||
}
|
||||
return optionList
|
||||
} else if (Array.isArray(options) && !options.length) {
|
||||
return [{ value: this.name, label: (this.label || this.name), id: nanoid(15) }]
|
||||
return [{ value: this.value, label: (this.label || this.name), id: this.context.id || nanoid(9) }]
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a getter/setter model factory
|
||||
* @return object
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
*/
|
||||
function defineModel (context) {
|
||||
return Object.defineProperty(context, 'model', {
|
||||
@ -260,7 +292,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
},
|
||||
formulateValue: {
|
||||
type: [String, Number, Object, Boolean, Array],
|
||||
default: false
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: [String, Number, Object, Boolean, Array],
|
||||
@ -276,7 +308,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
},
|
||||
id: {
|
||||
type: [String, Boolean, Number],
|
||||
default: function () { return nanoid(9); }
|
||||
default: false
|
||||
},
|
||||
label: {
|
||||
type: [String, Boolean],
|
||||
@ -289,16 +321,47 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
help: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
context: context,
|
||||
classification: function classification () {
|
||||
data: function data () {
|
||||
return {
|
||||
defaultId: nanoid(9),
|
||||
localAttributes: {}
|
||||
}
|
||||
},
|
||||
computed: Object.assign({}, context,
|
||||
{classification: function classification () {
|
||||
var classification = this.$formulate.classify(this.type);
|
||||
return (classification === 'box' && this.options) ? 'group' : classification
|
||||
},
|
||||
component: function component () {
|
||||
return this.$formulate.component(this.type)
|
||||
return (this.classification === 'group') ? 'FormulateInputGroup' : this.$formulate.component(this.type)
|
||||
}}),
|
||||
watch: {
|
||||
'$attrs': {
|
||||
handler: function handler (value) {
|
||||
this.updateLocalAttributes(value);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
created: function created () {
|
||||
this.updateLocalAttributes(this.$attrs);
|
||||
},
|
||||
mounted: function mounted () {
|
||||
if (this.debug) {
|
||||
console.log('MOUNTED:' + this.$options.name + ':' + this.type);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateLocalAttributes: function updateLocalAttributes (value) {
|
||||
if (!shallowEqualObjects(value, this.localAttributes)) {
|
||||
this.localAttributes = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -417,7 +480,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
_c("label", {
|
||||
staticClass:
|
||||
"formulate-input-label formulate-input-label--before",
|
||||
attrs: { for: _vm.id },
|
||||
attrs: { for: _vm.context.attributes.id },
|
||||
domProps: { textContent: _vm._s(_vm.context.label) }
|
||||
})
|
||||
],
|
||||
@ -445,7 +508,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
_c("label", {
|
||||
staticClass:
|
||||
"formulate-input-label formulate-input-label--after",
|
||||
attrs: { for: _vm.id },
|
||||
attrs: { for: _vm.context.attributes.id },
|
||||
domProps: { textContent: _vm._s(_vm.context.label) }
|
||||
})
|
||||
],
|
||||
@ -565,7 +628,8 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
var options = ref.options;
|
||||
var labelPosition = ref.labelPosition;
|
||||
var attributes = ref.attributes;
|
||||
var rest = objectWithoutProperties( ref, ["options", "labelPosition", "attributes"] );
|
||||
var classification = ref.classification;
|
||||
var rest = objectWithoutProperties( ref, ["options", "labelPosition", "attributes", "classification"] );
|
||||
var context = rest;
|
||||
return this.options.map(function (option) { return this$1.groupItemContext(context, option); })
|
||||
}
|
||||
@ -650,10 +714,18 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
* Default base for input components.
|
||||
*/
|
||||
var FormulateInputMixin = {
|
||||
model: {
|
||||
prop: 'formulateValue',
|
||||
event: 'input'
|
||||
},
|
||||
props: {
|
||||
context: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
formulateValue: {
|
||||
type: [Object, Array, Boolean, String, Number],
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -667,7 +739,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
return this.context.attributes || {}
|
||||
},
|
||||
hasValue: function hasValue () {
|
||||
return !!this.context.model
|
||||
return !!this.model
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1008,7 +1080,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
return this.context.optionGroups || false
|
||||
},
|
||||
placeholderSelected: function placeholderSelected () {
|
||||
return !!(!this.hasValue && this.context.attributes.placeholder)
|
||||
return !!(!this.hasValue && this.context.attributes && this.context.attributes.placeholder)
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1258,6 +1330,7 @@ var Formulate = (function (exports, isPlainObject, nanoid) {
|
||||
for (var componentName in this.options.components) {
|
||||
Vue.component(componentName, this.options.components[componentName]);
|
||||
}
|
||||
Object.freeze(this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
165
dist/formulate.umd.js
vendored
165
dist/formulate.umd.js
vendored
@ -117,16 +117,33 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to reduce an object's properties
|
||||
* @param {Object} original
|
||||
* @param {Function} callback
|
||||
* @param {*} accumulator
|
||||
* Shallow equal.
|
||||
* @param {} objA
|
||||
* @param {*} objB
|
||||
*/
|
||||
function reduce (original, callback, accumulator) {
|
||||
for (var key in original) {
|
||||
accumulator = callback(accumulator, key, original[key]);
|
||||
function shallowEqualObjects (objA, objB) {
|
||||
if (objA === objB) {
|
||||
return true
|
||||
}
|
||||
return accumulator
|
||||
if (!objA || !objB) {
|
||||
return false
|
||||
}
|
||||
var aKeys = Object.keys(objA);
|
||||
var bKeys = Object.keys(objB);
|
||||
var len = aKeys.length;
|
||||
|
||||
if (bKeys.length !== len) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
var key = aKeys[i];
|
||||
|
||||
if (objA[key] !== objB[key]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
@ -134,36 +151,45 @@
|
||||
* render that element.
|
||||
* @return {object}
|
||||
*/
|
||||
function context () {
|
||||
return defineModel.call(this, Object.assign({
|
||||
type: this.type,
|
||||
value: this.value,
|
||||
classification: this.classification,
|
||||
component: this.component,
|
||||
id: this.id,
|
||||
label: this.label,
|
||||
labelPosition: labelPosition.call(this),
|
||||
attributes: attributeReducer.call(this, this.$attrs)
|
||||
}, typeContext.call(this)))
|
||||
}
|
||||
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,
|
||||
classification: this.classification,
|
||||
component: this.component,
|
||||
id: this.id || this.defaultId,
|
||||
label: this.label,
|
||||
labelPosition: this.logicalLabelPosition,
|
||||
attributes: this.elementAttributes},
|
||||
this.typeContext))
|
||||
},
|
||||
typeContext: typeContext,
|
||||
elementAttributes: elementAttributes,
|
||||
logicalLabelPosition: logicalLabelPosition
|
||||
};
|
||||
|
||||
/**
|
||||
* Given (this.type), return an object to merge with the context
|
||||
* @return {object}
|
||||
* @return {object}
|
||||
*/
|
||||
function typeContext () {
|
||||
var this$1 = this;
|
||||
|
||||
switch (this.classification) {
|
||||
case 'select':
|
||||
return {
|
||||
options: createOptionList(this.options),
|
||||
optionGroups: this.optionGroups ? map(this.optionGroups, function (k, v) { return createOptionList(v); }) : false,
|
||||
options: createOptionList.call(this, this.options),
|
||||
optionGroups: this.optionGroups ? map(this.optionGroups, function (k, v) { return createOptionList.call(this$1, v); }) : false,
|
||||
placeholder: this.$attrs.placeholder || false
|
||||
}
|
||||
case 'group':
|
||||
if (this.options) {
|
||||
return {
|
||||
options: createOptionList(this.options),
|
||||
component: 'FormulateInputGroup'
|
||||
options: createOptionList.call(this, this.options)
|
||||
}
|
||||
}
|
||||
break
|
||||
@ -176,20 +202,21 @@
|
||||
* Reducer for attributes that will be applied to each core input element.
|
||||
* @return {object}
|
||||
*/
|
||||
function attributeReducer (attributes) {
|
||||
if ( attributes === void 0 ) attributes = {};
|
||||
|
||||
function elementAttributes () {
|
||||
var attrs = Object.assign({}, this.localAttributes);
|
||||
if (this.id) {
|
||||
attributes.id = this.id;
|
||||
attrs.id = this.id;
|
||||
} else {
|
||||
attrs.id = this.defaultId;
|
||||
}
|
||||
return attributes
|
||||
return attrs
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the a best-guess location for the label (before or after).
|
||||
* @return {string} before|after
|
||||
*/
|
||||
function labelPosition () {
|
||||
function logicalLabelPosition () {
|
||||
if (this.labelPosition) {
|
||||
return this.labelPosition
|
||||
}
|
||||
@ -208,17 +235,22 @@
|
||||
* @return {array}
|
||||
*/
|
||||
function createOptionList (options) {
|
||||
if (!Array.isArray(options)) {
|
||||
return reduce(options, function (options, value, label) { return options.concat({ value: value, label: label, id: nanoid(15) }); }, [])
|
||||
if (!Array.isArray(options) && options && typeof options === 'object') {
|
||||
var optionList = [];
|
||||
var that = this;
|
||||
for (var value in options) {
|
||||
optionList.push({ value: value, label: options[value], id: ((that.elementAttributes.id) + "_" + value) });
|
||||
}
|
||||
return optionList
|
||||
} else if (Array.isArray(options) && !options.length) {
|
||||
return [{ value: this.name, label: (this.label || this.name), id: nanoid(15) }]
|
||||
return [{ value: this.value, label: (this.label || this.name), id: this.context.id || nanoid(9) }]
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a getter/setter model factory
|
||||
* @return object
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
*/
|
||||
function defineModel (context) {
|
||||
return Object.defineProperty(context, 'model', {
|
||||
@ -263,7 +295,7 @@
|
||||
},
|
||||
formulateValue: {
|
||||
type: [String, Number, Object, Boolean, Array],
|
||||
default: false
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: [String, Number, Object, Boolean, Array],
|
||||
@ -279,7 +311,7 @@
|
||||
},
|
||||
id: {
|
||||
type: [String, Boolean, Number],
|
||||
default: function () { return nanoid(9); }
|
||||
default: false
|
||||
},
|
||||
label: {
|
||||
type: [String, Boolean],
|
||||
@ -292,16 +324,47 @@
|
||||
help: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
context: context,
|
||||
classification: function classification () {
|
||||
data: function data () {
|
||||
return {
|
||||
defaultId: nanoid(9),
|
||||
localAttributes: {}
|
||||
}
|
||||
},
|
||||
computed: Object.assign({}, context,
|
||||
{classification: function classification () {
|
||||
var classification = this.$formulate.classify(this.type);
|
||||
return (classification === 'box' && this.options) ? 'group' : classification
|
||||
},
|
||||
component: function component () {
|
||||
return this.$formulate.component(this.type)
|
||||
return (this.classification === 'group') ? 'FormulateInputGroup' : this.$formulate.component(this.type)
|
||||
}}),
|
||||
watch: {
|
||||
'$attrs': {
|
||||
handler: function handler (value) {
|
||||
this.updateLocalAttributes(value);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
created: function created () {
|
||||
this.updateLocalAttributes(this.$attrs);
|
||||
},
|
||||
mounted: function mounted () {
|
||||
if (this.debug) {
|
||||
console.log('MOUNTED:' + this.$options.name + ':' + this.type);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateLocalAttributes: function updateLocalAttributes (value) {
|
||||
if (!shallowEqualObjects(value, this.localAttributes)) {
|
||||
this.localAttributes = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -420,7 +483,7 @@
|
||||
_c("label", {
|
||||
staticClass:
|
||||
"formulate-input-label formulate-input-label--before",
|
||||
attrs: { for: _vm.id },
|
||||
attrs: { for: _vm.context.attributes.id },
|
||||
domProps: { textContent: _vm._s(_vm.context.label) }
|
||||
})
|
||||
],
|
||||
@ -448,7 +511,7 @@
|
||||
_c("label", {
|
||||
staticClass:
|
||||
"formulate-input-label formulate-input-label--after",
|
||||
attrs: { for: _vm.id },
|
||||
attrs: { for: _vm.context.attributes.id },
|
||||
domProps: { textContent: _vm._s(_vm.context.label) }
|
||||
})
|
||||
],
|
||||
@ -568,7 +631,8 @@
|
||||
var options = ref.options;
|
||||
var labelPosition = ref.labelPosition;
|
||||
var attributes = ref.attributes;
|
||||
var rest = objectWithoutProperties( ref, ["options", "labelPosition", "attributes"] );
|
||||
var classification = ref.classification;
|
||||
var rest = objectWithoutProperties( ref, ["options", "labelPosition", "attributes", "classification"] );
|
||||
var context = rest;
|
||||
return this.options.map(function (option) { return this$1.groupItemContext(context, option); })
|
||||
}
|
||||
@ -653,10 +717,18 @@
|
||||
* Default base for input components.
|
||||
*/
|
||||
var FormulateInputMixin = {
|
||||
model: {
|
||||
prop: 'formulateValue',
|
||||
event: 'input'
|
||||
},
|
||||
props: {
|
||||
context: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
formulateValue: {
|
||||
type: [Object, Array, Boolean, String, Number],
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -670,7 +742,7 @@
|
||||
return this.context.attributes || {}
|
||||
},
|
||||
hasValue: function hasValue () {
|
||||
return !!this.context.model
|
||||
return !!this.model
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1011,7 +1083,7 @@
|
||||
return this.context.optionGroups || false
|
||||
},
|
||||
placeholderSelected: function placeholderSelected () {
|
||||
return !!(!this.hasValue && this.context.attributes.placeholder)
|
||||
return !!(!this.hasValue && this.context.attributes && this.context.attributes.placeholder)
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1261,6 +1333,7 @@
|
||||
for (var componentName in this.options.components) {
|
||||
Vue.component(componentName, this.options.components[componentName]);
|
||||
}
|
||||
Object.freeze(this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,7 @@
|
||||
>
|
||||
<label
|
||||
class="formulate-input-label formulate-input-label--before"
|
||||
:for="id"
|
||||
:for="context.attributes.id"
|
||||
v-text="context.label"
|
||||
/>
|
||||
</slot>
|
||||
@ -29,7 +29,7 @@
|
||||
>
|
||||
<label
|
||||
class="formulate-input-label formulate-input-label--after"
|
||||
:for="id"
|
||||
:for="context.attributes.id"
|
||||
v-text="context.label"
|
||||
/>
|
||||
</slot>
|
||||
@ -44,7 +44,9 @@
|
||||
|
||||
<script>
|
||||
import context from './libs/context'
|
||||
import { shallowEqualObjects } from './libs/utils'
|
||||
import nanoid from 'nanoid'
|
||||
import library from './libs/library'
|
||||
|
||||
export default {
|
||||
name: 'FormulateInput',
|
||||
@ -60,7 +62,7 @@ export default {
|
||||
},
|
||||
formulateValue: {
|
||||
type: [String, Number, Object, Boolean, Array],
|
||||
default: false
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: [String, Number, Object, Boolean, Array],
|
||||
@ -76,7 +78,7 @@ export default {
|
||||
},
|
||||
id: {
|
||||
type: [String, Boolean, Number],
|
||||
default: () => nanoid(9)
|
||||
default: false
|
||||
},
|
||||
label: {
|
||||
type: [String, Boolean],
|
||||
@ -89,16 +91,49 @@ export default {
|
||||
help: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
defaultId: nanoid(9),
|
||||
localAttributes: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
context,
|
||||
...context,
|
||||
classification () {
|
||||
const classification = this.$formulate.classify(this.type)
|
||||
return (classification === 'box' && this.options) ? 'group' : classification
|
||||
},
|
||||
component () {
|
||||
return this.$formulate.component(this.type)
|
||||
return (this.classification === 'group') ? 'FormulateInputGroup' : this.$formulate.component(this.type)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$attrs': {
|
||||
handler (value) {
|
||||
this.updateLocalAttributes(value)
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.updateLocalAttributes(this.$attrs)
|
||||
},
|
||||
mounted () {
|
||||
if (this.debug) {
|
||||
console.log('MOUNTED:' + this.$options.name + ':' + this.type)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateLocalAttributes (value) {
|
||||
if (!shallowEqualObjects(value, this.localAttributes)) {
|
||||
this.localAttributes = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ export default {
|
||||
return this.context.options || []
|
||||
},
|
||||
optionsWithContext () {
|
||||
const { options, labelPosition, attributes, ...context } = this.context
|
||||
const { options, labelPosition, attributes, classification, ...context } = this.context
|
||||
return this.options.map(option => this.groupItemContext(context, option))
|
||||
}
|
||||
},
|
||||
|
@ -2,10 +2,18 @@
|
||||
* Default base for input components.
|
||||
*/
|
||||
export default {
|
||||
model: {
|
||||
prop: 'formulateValue',
|
||||
event: 'input'
|
||||
},
|
||||
props: {
|
||||
context: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
formulateValue: {
|
||||
type: [Object, Array, Boolean, String, Number],
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -19,7 +27,7 @@ export default {
|
||||
return this.context.attributes || {}
|
||||
},
|
||||
hasValue () {
|
||||
return !!this.context.model
|
||||
return !!this.model
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ class Formulate {
|
||||
for (var componentName in this.options.components) {
|
||||
Vue.component(componentName, this.options.components[componentName])
|
||||
}
|
||||
Object.freeze(this)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,7 +61,7 @@ export default {
|
||||
return this.context.optionGroups || false
|
||||
},
|
||||
placeholderSelected () {
|
||||
return !!(!this.hasValue && this.context.attributes.placeholder)
|
||||
return !!(!this.hasValue && this.context.attributes && this.context.attributes.placeholder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,36 +6,45 @@ import { reduce, map } from './utils'
|
||||
* render that element.
|
||||
* @return {object}
|
||||
*/
|
||||
export default function context () {
|
||||
return defineModel.call(this, Object.assign({
|
||||
type: this.type,
|
||||
value: this.value,
|
||||
classification: this.classification,
|
||||
component: this.component,
|
||||
id: this.id,
|
||||
label: this.label,
|
||||
labelPosition: labelPosition.call(this),
|
||||
attributes: attributeReducer.call(this, this.$attrs)
|
||||
}, typeContext.call(this)))
|
||||
export default {
|
||||
context () {
|
||||
if (this.debug) {
|
||||
console.log(`${this.type} re-context`)
|
||||
}
|
||||
return defineModel.call(this, {
|
||||
type: this.type,
|
||||
value: this.value,
|
||||
classification: this.classification,
|
||||
component: this.component,
|
||||
id: this.id || this.defaultId,
|
||||
label: this.label,
|
||||
labelPosition: this.logicalLabelPosition,
|
||||
attributes: this.elementAttributes,
|
||||
...this.typeContext
|
||||
})
|
||||
},
|
||||
typeContext,
|
||||
elementAttributes,
|
||||
logicalLabelPosition
|
||||
}
|
||||
|
||||
/**
|
||||
* Given (this.type), return an object to merge with the context
|
||||
* @return {object}
|
||||
* @return {object}
|
||||
*/
|
||||
function typeContext () {
|
||||
switch (this.classification) {
|
||||
case 'select':
|
||||
return {
|
||||
options: createOptionList(this.options),
|
||||
optionGroups: this.optionGroups ? map(this.optionGroups, (k, v) => createOptionList(v)) : false,
|
||||
options: createOptionList.call(this, this.options),
|
||||
optionGroups: this.optionGroups ? map(this.optionGroups, (k, v) => createOptionList.call(this, v)) : false,
|
||||
placeholder: this.$attrs.placeholder || false
|
||||
}
|
||||
case 'group':
|
||||
if (this.options) {
|
||||
return {
|
||||
options: createOptionList(this.options),
|
||||
component: 'FormulateInputGroup'
|
||||
options: createOptionList.call(this, this.options)
|
||||
}
|
||||
}
|
||||
break
|
||||
@ -48,18 +57,21 @@ function typeContext () {
|
||||
* Reducer for attributes that will be applied to each core input element.
|
||||
* @return {object}
|
||||
*/
|
||||
function attributeReducer (attributes = {}) {
|
||||
function elementAttributes () {
|
||||
const attrs = Object.assign({}, this.localAttributes)
|
||||
if (this.id) {
|
||||
attributes.id = this.id
|
||||
attrs.id = this.id
|
||||
} else {
|
||||
attrs.id = this.defaultId
|
||||
}
|
||||
return attributes
|
||||
return attrs
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the a best-guess location for the label (before or after).
|
||||
* @return {string} before|after
|
||||
*/
|
||||
function labelPosition () {
|
||||
function logicalLabelPosition () {
|
||||
if (this.labelPosition) {
|
||||
return this.labelPosition
|
||||
}
|
||||
@ -78,17 +90,22 @@ function labelPosition () {
|
||||
* @return {array}
|
||||
*/
|
||||
function createOptionList (options) {
|
||||
if (!Array.isArray(options)) {
|
||||
return reduce(options, (options, value, label) => options.concat({ value, label, id: nanoid(15) }), [])
|
||||
if (!Array.isArray(options) && options && typeof options === 'object') {
|
||||
const optionList = []
|
||||
const that = this
|
||||
for (const value in options) {
|
||||
optionList.push({ value, label: options[value], id: `${that.elementAttributes.id}_${value}` })
|
||||
}
|
||||
return optionList
|
||||
} else if (Array.isArray(options) && !options.length) {
|
||||
return [{ value: this.name, label: (this.label || this.name), id: nanoid(15) }]
|
||||
return [{ value: this.value, label: (this.label || this.name), id: this.context.id || nanoid(9) }]
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a getter/setter model factory
|
||||
* @return object
|
||||
* Defines the model used throughout the existing context.
|
||||
* @param {object} context
|
||||
*/
|
||||
function defineModel (context) {
|
||||
return Object.defineProperty(context, 'model', {
|
||||
|
@ -39,3 +39,33 @@ export function reduce (original, callback, accumulator) {
|
||||
}
|
||||
return accumulator
|
||||
}
|
||||
|
||||
/**
|
||||
* Shallow equal.
|
||||
* @param {} objA
|
||||
* @param {*} objB
|
||||
*/
|
||||
export function shallowEqualObjects (objA, objB) {
|
||||
if (objA === objB) {
|
||||
return true
|
||||
}
|
||||
if (!objA || !objB) {
|
||||
return false
|
||||
}
|
||||
var aKeys = Object.keys(objA)
|
||||
var bKeys = Object.keys(objB)
|
||||
var len = aKeys.length
|
||||
|
||||
if (bKeys.length !== len) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
var key = aKeys[i]
|
||||
|
||||
if (objA[key] !== objB[key]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -42,3 +42,37 @@ test('labelPosition of type "checkbox" with options defaults to before', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'checkbox', options: {a: '1', b: '2'}}})
|
||||
expect(wrapper.vm.context.labelPosition).toBe('before')
|
||||
})
|
||||
|
||||
|
||||
test('type radio renders multiple inputs with options', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'radio', options: {a: '1', b: '2'} } })
|
||||
expect(wrapper.findAll('input[type="radio"]').length).toBe(2)
|
||||
})
|
||||
|
||||
test('type "radio" auto generate ids if not provided', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'radio', options: {a: '1', b: '2'} } })
|
||||
expect(wrapper.findAll('input[type="radio"]').is('[id]')).toBe(true)
|
||||
})
|
||||
|
||||
/**
|
||||
* Test data binding
|
||||
*/
|
||||
|
||||
test('type "checkbox" sets array of values via v-model', () => {
|
||||
const wrapper = mount({
|
||||
data () {
|
||||
return {
|
||||
checkboxValues: []
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<FormulateInput type="checkbox" v-model="checkboxValues" :options="{foo: 'Foo', bar: 'Bar', fooey: 'Fooey'}" />
|
||||
</div>
|
||||
`
|
||||
})
|
||||
const fooInputs = wrapper.findAll('input[value^="foo"]')
|
||||
expect(fooInputs.length).toBe(2)
|
||||
fooInputs.setChecked(true)
|
||||
expect(wrapper.vm.checkboxValues).toEqual(['foo', 'fooey'])
|
||||
})
|
||||
|
@ -3,6 +3,7 @@ import { mount } from '@vue/test-utils'
|
||||
import Formulate from '../dist/formulate.esm.js'
|
||||
import FormulateInput from '../src/FormulateInput.vue'
|
||||
import FormulateInputText from '../src/inputs/FormulateInputText.vue'
|
||||
import { doesNotReject } from 'assert';
|
||||
|
||||
Vue.use(Formulate)
|
||||
|
||||
@ -76,13 +77,13 @@ test('type "week" renders a text input', () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* Test functionality to text inputs
|
||||
* 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.id}"]`).exists()).toBe(true)
|
||||
expect(wrapper.find(`input[id="${wrapper.vm.context.attributes.id}"]`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
test('text inputs dont have labels', () => {
|
||||
@ -92,7 +93,7 @@ test('text inputs dont have labels', () => {
|
||||
|
||||
test('text inputs can have labels', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'text', label: 'Field label' } })
|
||||
expect(wrapper.find(`label[for="${wrapper.vm.id}"]`).exists()).toBe(true)
|
||||
expect(wrapper.find(`label[for="${wrapper.vm.context.attributes.id}"]`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
test('text inputs dont have help text', () => {
|
||||
@ -104,3 +105,39 @@ 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>
|
||||
`
|
||||
})
|
||||
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)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user