Fixes form submissions, and a bug that prevented value props from populating forms
This commit is contained in:
parent
d7e3859951
commit
839f0936ed
2
dist/formulate.esm.js
vendored
2
dist/formulate.esm.js
vendored
@ -1776,7 +1776,7 @@ var script$1 = {
|
|||||||
this.$emit('submit-raw', submission);
|
this.$emit('submit-raw', submission);
|
||||||
submission.hasValidationErrors()
|
submission.hasValidationErrors()
|
||||||
.then(function (hasErrors) { return hasErrors ? false : submission.values(); })
|
.then(function (hasErrors) { return hasErrors ? false : submission.values(); })
|
||||||
.then(function (json) { return this$1.$emit('submit', json); });
|
.then(function (json) { return json !== false ? this$1.$emit('submit', json) : null; });
|
||||||
},
|
},
|
||||||
showErrors: function showErrors () {
|
showErrors: function showErrors () {
|
||||||
for (var fieldName in this.registry) {
|
for (var fieldName in this.registry) {
|
||||||
|
2
dist/formulate.min.js
vendored
2
dist/formulate.min.js
vendored
@ -1779,7 +1779,7 @@ var Formulate = (function (exports, isUrl, nanoid, isPlainObject) {
|
|||||||
this.$emit('submit-raw', submission);
|
this.$emit('submit-raw', submission);
|
||||||
submission.hasValidationErrors()
|
submission.hasValidationErrors()
|
||||||
.then(function (hasErrors) { return hasErrors ? false : submission.values(); })
|
.then(function (hasErrors) { return hasErrors ? false : submission.values(); })
|
||||||
.then(function (json) { return this$1.$emit('submit', json); });
|
.then(function (json) { return json !== false ? this$1.$emit('submit', json) : null; });
|
||||||
},
|
},
|
||||||
showErrors: function showErrors () {
|
showErrors: function showErrors () {
|
||||||
for (var fieldName in this.registry) {
|
for (var fieldName in this.registry) {
|
||||||
|
2
dist/formulate.umd.js
vendored
2
dist/formulate.umd.js
vendored
@ -1782,7 +1782,7 @@
|
|||||||
this.$emit('submit-raw', submission);
|
this.$emit('submit-raw', submission);
|
||||||
submission.hasValidationErrors()
|
submission.hasValidationErrors()
|
||||||
.then(function (hasErrors) { return hasErrors ? false : submission.values(); })
|
.then(function (hasErrors) { return hasErrors ? false : submission.values(); })
|
||||||
.then(function (json) { return this$1.$emit('submit', json); });
|
.then(function (json) { return json !== false ? this$1.$emit('submit', json) : null; });
|
||||||
},
|
},
|
||||||
showErrors: function showErrors () {
|
showErrors: function showErrors () {
|
||||||
for (var fieldName in this.registry) {
|
for (var fieldName in this.registry) {
|
||||||
|
2
dist/snow.css
vendored
2
dist/snow.css
vendored
@ -1,5 +1,5 @@
|
|||||||
.formulate-input {
|
.formulate-input {
|
||||||
margin-bottom: 2em; }
|
margin-bottom: 1.5em; }
|
||||||
.formulate-input .formulate-input-label {
|
.formulate-input .formulate-input-label {
|
||||||
display: block;
|
display: block;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
4
dist/snow.min.css
vendored
4
dist/snow.min.css
vendored
File diff suppressed because one or more lines are too long
@ -26,10 +26,10 @@ export default class FormSubmission {
|
|||||||
values () {
|
values () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const pending = []
|
const pending = []
|
||||||
const values = cloneDeep(this.form.internalModelProxy)
|
const values = cloneDeep(this.form.internalFormModelProxy)
|
||||||
for (const key in values) {
|
for (const key in values) {
|
||||||
if (typeof this.form.internalModelProxy[key] === 'object' && this.form.internalModelProxy[key] instanceof FileUpload) {
|
if (typeof this.form.internalFormModelProxy[key] === 'object' && this.form.internalFormModelProxy[key] instanceof FileUpload) {
|
||||||
pending.push(this.form.internalModelProxy[key].upload())
|
pending.push(this.form.internalFormModelProxy[key].upload())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -85,11 +85,20 @@ export default {
|
|||||||
},
|
},
|
||||||
register (field, component) {
|
register (field, component) {
|
||||||
this.registry[field] = component
|
this.registry[field] = component
|
||||||
if (!component.$options.propsData.hasOwnProperty('formulateValue') && this.hasFormulateValue && this.formulateValue[field]) {
|
const hasVModelValue = Object.prototype.hasOwnProperty.call(component.$options.propsData, 'formulateValue')
|
||||||
|
const hasValue = Object.prototype.hasOwnProperty.call(component.$options.propsData, 'value')
|
||||||
|
if (
|
||||||
|
!hasVModelValue &&
|
||||||
|
this.hasFormulateValue &&
|
||||||
|
this.formulateValue[field]
|
||||||
|
) {
|
||||||
// In the case that the form is carrying an initial value and the
|
// In the case that the form is carrying an initial value and the
|
||||||
// element is not, set it directly.
|
// element is not, set it directly.
|
||||||
component.context.model = this.formulateValue[field]
|
component.context.model = this.formulateValue[field]
|
||||||
} else if (component.$options.propsData.hasOwnProperty('formulateValue') && !shallowEqualObjects(component.internalModelProxy, this.formulateValue[field])) {
|
} else if (
|
||||||
|
(hasVModelValue || hasValue) &&
|
||||||
|
!shallowEqualObjects(component.internalModelProxy, this.formulateValue[field])
|
||||||
|
) {
|
||||||
this.setFieldValue(field, component.internalModelProxy)
|
this.setFieldValue(field, component.internalModelProxy)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -98,9 +107,9 @@ export default {
|
|||||||
this.showErrors()
|
this.showErrors()
|
||||||
const submission = new FormSubmission(this)
|
const submission = new FormSubmission(this)
|
||||||
this.$emit('submit-raw', submission)
|
this.$emit('submit-raw', submission)
|
||||||
submission.hasValidationErrors()
|
return submission.hasValidationErrors()
|
||||||
.then(hasErrors => hasErrors ? false : submission.values())
|
.then(hasErrors => hasErrors ? false : submission.values())
|
||||||
.then(json => this.$emit('submit', json))
|
.then(json => json !== false ? this.$emit('submit', json) : null)
|
||||||
},
|
},
|
||||||
showErrors () {
|
showErrors () {
|
||||||
for (const fieldName in this.registry) {
|
for (const fieldName in this.registry) {
|
||||||
|
@ -203,7 +203,7 @@ export function cloneDeep (obj) {
|
|||||||
const newObj = {}
|
const newObj = {}
|
||||||
for (const key in obj) {
|
for (const key in obj) {
|
||||||
if (obj[key] instanceof FileUpload || isValueType(obj[key])) {
|
if (obj[key] instanceof FileUpload || isValueType(obj[key])) {
|
||||||
newObj[key] = obj
|
newObj[key] = obj[key]
|
||||||
} else {
|
} else {
|
||||||
newObj[key] = cloneDeep(obj[key])
|
newObj[key] = cloneDeep(obj[key])
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,20 @@ describe('FormulateForm', () => {
|
|||||||
expect(wrapper.find('input').element.value).toBe('123')
|
expect(wrapper.find('input').element.value).toBe('123')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('lets fields set form initial value with value prop', () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formValues: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<FormulateForm v-model="formValues">
|
||||||
|
<FormulateInput name="name" value="123" />
|
||||||
|
</FormulateForm>`
|
||||||
|
})
|
||||||
|
expect(wrapper.vm.formValues).toEqual({ name: '123' })
|
||||||
|
})
|
||||||
|
|
||||||
it('receives updates to form model when individual fields are edited', () => {
|
it('receives updates to form model when individual fields are edited', () => {
|
||||||
const wrapper = mount({
|
const wrapper = mount({
|
||||||
data () {
|
data () {
|
||||||
@ -132,7 +146,7 @@ describe('FormulateForm', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
it('it emits an instance of FormSubmission', async () => {
|
it('emits an instance of FormSubmission', async () => {
|
||||||
const wrapper = mount(FormulateForm, {
|
const wrapper = mount(FormulateForm, {
|
||||||
slots: { default: '<FormulateInput type="text" formulate-value="123" name="testinput" />' }
|
slots: { default: '<FormulateInput type="text" formulate-value="123" name="testinput" />' }
|
||||||
})
|
})
|
||||||
@ -141,7 +155,7 @@ describe('FormulateForm', () => {
|
|||||||
expect(wrapper.emitted('submit-raw')[0][0]).toBeInstanceOf(FormSubmission)
|
expect(wrapper.emitted('submit-raw')[0][0]).toBeInstanceOf(FormSubmission)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('it resolves hasValidationErrors to true', async () => {
|
it('resolves hasValidationErrors to true', async () => {
|
||||||
const wrapper = mount(FormulateForm, {
|
const wrapper = mount(FormulateForm, {
|
||||||
slots: { default: '<FormulateInput type="text" validation="required" name="testinput" />' }
|
slots: { default: '<FormulateInput type="text" validation="required" name="testinput" />' }
|
||||||
})
|
})
|
||||||
@ -150,4 +164,15 @@ describe('FormulateForm', () => {
|
|||||||
const submission = wrapper.emitted('submit-raw')[0][0]
|
const submission = wrapper.emitted('submit-raw')[0][0]
|
||||||
expect(await submission.hasValidationErrors()).toBe(true)
|
expect(await submission.hasValidationErrors()).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('resolves submitted form values to an object', async () => {
|
||||||
|
const wrapper = mount(FormulateForm, {
|
||||||
|
slots: { default: '<FormulateInput type="text" validation="required" name="testinput" value="Justin" />' }
|
||||||
|
})
|
||||||
|
wrapper.find('form').trigger('submit')
|
||||||
|
await flushPromises()
|
||||||
|
const submission = await wrapper.vm.formSubmitted()
|
||||||
|
await flushPromises()
|
||||||
|
expect(submission).toEqual({testinput: 'Justin'})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { parseRules, regexForFormat } from '@/libs/utils'
|
import { parseRules, regexForFormat, cloneDeep, isValueType } from '@/libs/utils'
|
||||||
import rules from '@/libs/rules'
|
import rules from '@/libs/rules'
|
||||||
|
import FileUpload from '@/FileUpload';
|
||||||
|
|
||||||
describe('parseRules', () => {
|
describe('parseRules', () => {
|
||||||
it('parses single string rules, returning empty arguments array', () => {
|
it('parses single string rules, returning empty arguments array', () => {
|
||||||
@ -83,3 +84,36 @@ describe('regexForFormat', () => {
|
|||||||
|
|
||||||
it('fails date like YYYY-MM-DD with out of bounds day', () => expect(regexForFormat('YYYY-MM-DD').test('1987-01-32')).toBe(false))
|
it('fails date like YYYY-MM-DD with out of bounds day', () => expect(regexForFormat('YYYY-MM-DD').test('1987-01-32')).toBe(false))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('isValueType', () => {
|
||||||
|
it('passes on strings', () => expect(isValueType('hello')).toBe(true))
|
||||||
|
|
||||||
|
it('passes on numbers', () => expect(isValueType(123)).toBe(true))
|
||||||
|
|
||||||
|
it('passes on booleans', () => expect(isValueType(false)).toBe(true))
|
||||||
|
|
||||||
|
it('passes on symbols', () => expect(isValueType(Symbol(123))).toBe(true))
|
||||||
|
|
||||||
|
it('passes on null', () => expect(isValueType(null)).toBe(true))
|
||||||
|
|
||||||
|
it('passes on undefined', () => expect(isValueType(undefined)).toBe(true))
|
||||||
|
|
||||||
|
it('fails on pojo', () => expect(isValueType({})).toBe(false))
|
||||||
|
|
||||||
|
it('fails on custom type', () => expect(isValueType(FileUpload)).toBe(false))
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('cloneDeep', () => {
|
||||||
|
it('basic objects stay the same', () => expect(cloneDeep({ a: 123, b: 'hello' })).toEqual({ a: 123, b: 'hello' }))
|
||||||
|
|
||||||
|
it('basic nested objects stay the same', () => {
|
||||||
|
expect(cloneDeep({ a: 123, b: { c: 'hello-world' } }))
|
||||||
|
.toEqual({ a: 123, b: { c: 'hello-world' } })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('simple pojo reference types are re-created', () => {
|
||||||
|
const c = { c: 'hello-world' }
|
||||||
|
const clone = cloneDeep({ a: 123, b: c })
|
||||||
|
expect(clone.b === c).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
.formulate-input {
|
.formulate-input {
|
||||||
margin-bottom: 2em;
|
margin-bottom: 1.5em;
|
||||||
|
|
||||||
.formulate-input-label {
|
.formulate-input-label {
|
||||||
display: block;
|
display: block;
|
||||||
|
Loading…
Reference in New Issue
Block a user