Adds support for new named form methods
This commit is contained in:
parent
1d869936c8
commit
2d097fadb4
2
dist/formulate.esm.js
vendored
2
dist/formulate.esm.js
vendored
File diff suppressed because one or more lines are too long
4
dist/formulate.min.js
vendored
4
dist/formulate.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/formulate.umd.js
vendored
2
dist/formulate.umd.js
vendored
File diff suppressed because one or more lines are too long
22
dist/snow.css
vendored
22
dist/snow.css
vendored
@ -330,22 +330,22 @@
|
|||||||
.formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove {
|
.formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
top: calc(50% - .75em);
|
top: calc(50% - .65em + .5em);
|
||||||
width: 1.5em;
|
width: 1.3em;
|
||||||
height: 1.5em;
|
height: 1.3em;
|
||||||
background-color: #cecece;
|
background-color: #cecece;
|
||||||
right: .75em;
|
right: .85em;
|
||||||
border-radius: 1.5em;
|
border-radius: 1.3em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color .2s; }
|
transition: background-color .2s; }
|
||||||
.formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove::before, .formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove::after {
|
.formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove::before, .formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(50% - .125em);
|
top: calc(50% - .1em);
|
||||||
left: 0.375em;
|
left: .325em;
|
||||||
display: block;
|
display: block;
|
||||||
width: .75em;
|
width: .65em;
|
||||||
height: .25em;
|
height: .2em;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
transform-origin: center center;
|
transform-origin: center center;
|
||||||
transition: transform .25s; }
|
transition: transform .25s; }
|
||||||
@ -354,8 +354,8 @@
|
|||||||
background-color: #dc2c2c; }
|
background-color: #dc2c2c; }
|
||||||
.formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove:hover::after, .formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove:hover::before {
|
.formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove:hover::after, .formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove:hover::before {
|
||||||
height: .2em;
|
height: .2em;
|
||||||
width: .9em;
|
width: .75em;
|
||||||
left: .3em;
|
left: .25em;
|
||||||
top: calc(50% - .075em); }
|
top: calc(50% - .075em); }
|
||||||
.formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove:hover::after {
|
.formulate-input[data-classification='group'] [data-is-repeatable] .formulate-input-group-repeatable-remove:hover::after {
|
||||||
transform: rotate(45deg); }
|
transform: rotate(45deg); }
|
||||||
|
2
dist/snow.min.css
vendored
2
dist/snow.min.css
vendored
File diff suppressed because one or more lines are too long
@ -103,10 +103,10 @@ class Formulate {
|
|||||||
* implementation is open to community review.
|
* implementation is open to community review.
|
||||||
*/
|
*/
|
||||||
nextId (vm) {
|
nextId (vm) {
|
||||||
const path = vm.$route && vm.$route.path || false
|
const path = vm.$route && vm.$route.path ? vm.$route.path : false
|
||||||
const pathPrefix = path ? vm.$route.path.replace(/[\/\\.\s]/g, '-') : 'global';
|
const pathPrefix = path ? vm.$route.path.replace(/[/\\.\s]/g, '-') : 'global'
|
||||||
if (!Object.prototype.hasOwnProperty.call(this.idRegistry, pathPrefix)) {
|
if (!Object.prototype.hasOwnProperty.call(this.idRegistry, pathPrefix)) {
|
||||||
this.idRegistry[pathPrefix] = 0;
|
this.idRegistry[pathPrefix] = 0
|
||||||
}
|
}
|
||||||
return `${this.options.idPrefix}${pathPrefix}-${++this.idRegistry[pathPrefix]}`
|
return `${this.options.idPrefix}${pathPrefix}-${++this.idRegistry[pathPrefix]}`
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ class Formulate {
|
|||||||
*/
|
*/
|
||||||
slotComponent (type, slot) {
|
slotComponent (type, slot) {
|
||||||
const def = this.options.library[type]
|
const def = this.options.library[type]
|
||||||
if (def.slotComponents && def.slotComponents[slot]) {
|
if (def && def.slotComponents && def.slotComponents[slot]) {
|
||||||
return def.slotComponents[slot]
|
return def.slotComponents[slot]
|
||||||
}
|
}
|
||||||
return this.options.slotComponents[slot]
|
return this.options.slotComponents[slot]
|
||||||
@ -297,6 +297,39 @@ class Formulate {
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset a form.
|
||||||
|
* @param {string} formName
|
||||||
|
* @param {object} initialValue
|
||||||
|
*/
|
||||||
|
reset (formName, initialValue = {}) {
|
||||||
|
this.resetValidation(formName)
|
||||||
|
this.setValues(formName, initialValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the form's validation messages.
|
||||||
|
* @param {string} formName
|
||||||
|
*/
|
||||||
|
resetValidation (formName) {
|
||||||
|
const form = this.registry.get(formName)
|
||||||
|
form.hideErrors(formName)
|
||||||
|
form.namedErrors = []
|
||||||
|
form.namedFieldErrors = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the form values.
|
||||||
|
* @param {string} formName
|
||||||
|
* @param {object} values
|
||||||
|
*/
|
||||||
|
setValues (formName, values) {
|
||||||
|
if (values && !Array.isArray(values) && typeof values === 'object') {
|
||||||
|
const form = this.registry.get(formName)
|
||||||
|
form.setValues({ ...values })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the file uploader.
|
* Get the file uploader.
|
||||||
*/
|
*/
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { shallowEqualObjects, arrayify, has } from './libs/utils'
|
import { arrayify, has } from './libs/utils'
|
||||||
import useRegistry, { useRegistryComputed, useRegistryMethods, useRegistryProviders } from './libs/registry'
|
import useRegistry, { useRegistryComputed, useRegistryMethods, useRegistryProviders } from './libs/registry'
|
||||||
import FormSubmission from './FormSubmission'
|
import FormSubmission from './FormSubmission'
|
||||||
|
|
||||||
@ -96,20 +96,12 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
formulateValue: {
|
formulateValue: {
|
||||||
handler (newValue, oldValue) {
|
handler (values) {
|
||||||
if (this.isVmodeled &&
|
if (this.isVmodeled &&
|
||||||
newValue &&
|
values &&
|
||||||
typeof newValue === 'object'
|
typeof values === 'object'
|
||||||
) {
|
) {
|
||||||
for (const field in newValue) {
|
this.setValues(values)
|
||||||
if (this.registry.has(field) &&
|
|
||||||
!shallowEqualObjects(newValue[field], this.proxy[field]) &&
|
|
||||||
!shallowEqualObjects(newValue[field], this.registry.get(field).proxy[field])
|
|
||||||
) {
|
|
||||||
this.setFieldValue(field, newValue[field])
|
|
||||||
this.registry.get(field).context.model = newValue[field]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
|
@ -155,10 +155,6 @@ export default {
|
|||||||
type: [String, Boolean],
|
type: [String, Boolean],
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
debug: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
errors: {
|
errors: {
|
||||||
type: [String, Array, Boolean],
|
type: [String, Array, Boolean],
|
||||||
default: false
|
default: false
|
||||||
|
@ -187,7 +187,12 @@ export function useRegistryMethods (without = []) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setFieldValue (field, value) {
|
setFieldValue (field, value) {
|
||||||
Object.assign(this.proxy, { [field]: value })
|
if (value === undefined) {
|
||||||
|
const { [field]: value, ...proxy } = this.proxy
|
||||||
|
this.proxy = proxy
|
||||||
|
} else {
|
||||||
|
Object.assign(this.proxy, { [field]: value })
|
||||||
|
}
|
||||||
this.$emit('input', Object.assign({}, this.proxy))
|
this.$emit('input', Object.assign({}, this.proxy))
|
||||||
},
|
},
|
||||||
getFormValues () {
|
getFormValues () {
|
||||||
@ -204,6 +209,26 @@ export function useRegistryMethods (without = []) {
|
|||||||
this.registry.map(input => {
|
this.registry.map(input => {
|
||||||
input.formShouldShowErrors = true
|
input.formShouldShowErrors = true
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
hideErrors () {
|
||||||
|
this.childrenShouldShowErrors = false
|
||||||
|
this.registry.map(input => {
|
||||||
|
input.formShouldShowErrors = false
|
||||||
|
input.behavioralErrorVisibility = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setValues (values) {
|
||||||
|
// Collect all keys, existing and incoming
|
||||||
|
const keys = Array.from(new Set(Object.keys(values).concat(Object.keys(this.proxy))))
|
||||||
|
keys.forEach(field => {
|
||||||
|
if (this.registry.has(field) &&
|
||||||
|
!shallowEqualObjects(values[field], this.proxy[field]) &&
|
||||||
|
!shallowEqualObjects(values[field], this.registry.get(field).proxy)
|
||||||
|
) {
|
||||||
|
this.setFieldValue(field, values[field])
|
||||||
|
this.registry.get(field).context.model = values[field]
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Object.keys(methods).reduce((withMethods, key) => {
|
return Object.keys(methods).reduce((withMethods, key) => {
|
||||||
|
@ -536,4 +536,65 @@ describe('FormulateForm', () => {
|
|||||||
expect(wrapper.findComponent(FormulateForm).vm.proxy).toEqual({ foo: 'bar' })
|
expect(wrapper.findComponent(FormulateForm).vm.proxy).toEqual({ foo: 'bar' })
|
||||||
expect(wrapper.vm.formData).toEqual({ foo: 'bar' })
|
expect(wrapper.vm.formData).toEqual({ foo: 'bar' })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('it allows the removal of properties in proxy.', async () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
template: `
|
||||||
|
<FormulateForm
|
||||||
|
v-model="formData"
|
||||||
|
name="login"
|
||||||
|
ref="form"
|
||||||
|
>
|
||||||
|
<FormulateInput type="text" name="username" validation="required" v-model="username" />
|
||||||
|
<FormulateInput type="password" name="password" validation="required|min:4,length" />
|
||||||
|
</FormulateForm>
|
||||||
|
`,
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formData: {},
|
||||||
|
username: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
wrapper.find('input[type="text"]').setValue('foo')
|
||||||
|
await flushPromises()
|
||||||
|
expect(wrapper.vm.username).toEqual('foo')
|
||||||
|
expect(wrapper.vm.formData).toEqual({ username: 'foo' })
|
||||||
|
wrapper.vm.$refs.form.setValues({})
|
||||||
|
await flushPromises()
|
||||||
|
expect(wrapper.vm.formData).toEqual({ username: '' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('it allows resetting a form, hiding validation and clearing inputs.', async () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
template: `
|
||||||
|
<FormulateForm
|
||||||
|
v-model="formData"
|
||||||
|
name="login"
|
||||||
|
>
|
||||||
|
<FormulateInput type="text" name="username" validation="required" />
|
||||||
|
<FormulateInput type="password" name="password" validation="required|min:4,length" />
|
||||||
|
</FormulateForm>
|
||||||
|
`,
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formData: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const password = wrapper.find('input[type="password"]')
|
||||||
|
password.setValue('foo')
|
||||||
|
password.trigger('blur')
|
||||||
|
wrapper.find('form').trigger('submit')
|
||||||
|
wrapper.vm.$formulate.handle({
|
||||||
|
inputErrors: { username: ['Failed'] }
|
||||||
|
}, 'login')
|
||||||
|
await flushPromises()
|
||||||
|
// First make sure we showed the errors
|
||||||
|
expect(wrapper.findAll('.formulate-input-error').length).toBe(3)
|
||||||
|
wrapper.vm.$formulate.reset('login')
|
||||||
|
await flushPromises()
|
||||||
|
expect(wrapper.findAll('.formulate-input-error').length).toBe(0)
|
||||||
|
expect(wrapper.vm.formData).toEqual({})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -294,9 +294,9 @@ describe('FormulateInput', () => {
|
|||||||
expect(wrapper.vm.context.visibleValidationErrors.length).toBe(2);
|
expect(wrapper.vm.context.visibleValidationErrors.length).toBe(2);
|
||||||
})
|
})
|
||||||
|
|
||||||
it('doesnt show errors on blur when set error-behavior is submit', async () => {
|
it('does not show errors on blur when set error-behavior is submit', async () => {
|
||||||
const wrapper = mount(FormulateInput, { propsData: {
|
const wrapper = mount(FormulateInput, { propsData: {
|
||||||
type: 'special',
|
type: 'text',
|
||||||
validation: 'required',
|
validation: 'required',
|
||||||
errorBehavior: 'submit',
|
errorBehavior: 'submit',
|
||||||
} })
|
} })
|
||||||
|
@ -413,12 +413,12 @@
|
|||||||
&-remove {
|
&-remove {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
top: calc(50% - .75em);
|
top: calc(50% - .65em + .5em);
|
||||||
width: 1.5em;
|
width: 1.3em;
|
||||||
height: 1.5em;
|
height: 1.3em;
|
||||||
background-color: $formulate-gray-d;
|
background-color: $formulate-gray-d;
|
||||||
right: .75em;
|
right: .85em;
|
||||||
border-radius: 1.5em;
|
border-radius: 1.3em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color .2s;
|
transition: background-color .2s;
|
||||||
|
|
||||||
@ -426,11 +426,11 @@
|
|||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(50% - .125em);
|
top: calc(50% - .1em);
|
||||||
left: 0.375em;
|
left: .325em;
|
||||||
display: block;
|
display: block;
|
||||||
width: .75em;
|
width: .65em;
|
||||||
height: .25em;
|
height: .2em;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
transform-origin: center center;
|
transform-origin: center center;
|
||||||
transition: transform .25s;
|
transition: transform .25s;
|
||||||
@ -443,8 +443,8 @@
|
|||||||
&::after,
|
&::after,
|
||||||
&::before {
|
&::before {
|
||||||
height: .2em;
|
height: .2em;
|
||||||
width: .9em;
|
width: .75em;
|
||||||
left: .3em;
|
left: .25em;
|
||||||
top: calc(50% - .075em);
|
top: calc(50% - .075em);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user