Using Form Data
Learn how submit, store and manage form data using Vueform.
Storing Form Data
By default Vueform stores form data internally which can be accessed via data
property:
<template>
<Vueform ref="form$">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup() {
const form$ = ref(null)
onMounted(() => {
console.log(form$.value.data)
})
return {
form$,
}
}
}
</script>
The same thing we can do with Options API:
<template>
<Vueform ref="form$">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
export default {
mounted() {
console.log(this.$refs.form$.data)
}
}
</script>
Every time we are referencing
form$.value
using Composition API (setup()
) it's equivalent tothis.$refs.form$
in Options API.
Storing Data Externally
We can have an external object to store form data using v-model
:
<template>
<Vueform v-model="data">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
export default {
data() {
return {
data: {}
}
}
}
</script>
Contrary to regular v-model
, two-way data binding is disabled by default in Vueform.
This means that when the form data is changed internally (eg. by user input) the changes are reflected in the v-model
object, but not the other way around. If the v-model
object is changed outside of Vueform, changes will not be synchronize back to the elements. This is also true for any inital data the v-model
object might have.
Synchronizing External Data
Even though two-way data binding is disabled by default, it can be enabled with sync
:
<template>
<Vueform v-model="data" sync>
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
export default {
data() {
return {
data: {
name: 'John Doe',
email: 'john@doe.com'
}
}
}
}
</script>
When sync
is enabled whenever the data if v-model
object is changed, the changes will be reflected in both the external object and form elements.
When using a lot elements or deeply nested elements the performance can be affected if
sync
is enabled. Make sure to only usesync
if you actually need two-way data binding.
Using Vuex to Store Data
To use Vueform with Vuex first we need to register an object in state and a mutation:
export default {
state: {
forms: {
registration: {}
}
},
mutations: {
UPDATE_FORM_DATA(state, value) {
state.forms[value.form] = value.data
}
}
}
Then we can use :model-value
and @update:modelValue
(or :value
and @input
in Vue.js 2) to set the Vuex state object as a value and commit a mutation when the data is changed.
Vueform has data
property and update
method that we can use to get and set data form data:
<template>
<Vueform :model-value="data" @update:modelValue="updateData"> <!-- :value="data" @input="updateData" in Vue.js 2 -->
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState({
data: => state.forms.registration
})
},
methods: {
updateData() {
this.$store.commit('UPDATE_FORM_DATA', {
form: 'registration',
data: this.data,
})
}
}
}
</script>
If we want we can also enable sync
option to synchronize Vueform data with the state object when it is changed outside of Vueform:
<Vueform :model-value="data" @updateModel:input="updateData" sync>
Managing Form Data via API
If we aren't using v-model
and Vueform data is handled internally we can still access and update it programmatically:
<template>
<Vueform ref="form$">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup(props, context) {
const form$ = ref(null)
onMounted(() => {
console.log(form$.value.data) // outputs form data
form$.value.update({ // updates form data
name: 'John Doe',
email: 'john@doe.com',
})
})
return { form$ }
}
}
</script>
We are using a ref
to access Vueform
component, which allows us to access its API.
Loading Form Data
When a form is mounted we can load initial data. Here's an example for loading user data from database:
<template>
<Vueform ref="form$">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
import { ref, onMounted } from 'vue'
import axios from 'axios'
export default {
setup(props, context) {
const form$ = ref(null)
onMounted(async () => {
const data = (await axios.get('/user/1')).data
form$.value.load(data)
})
return { form$ }
}
}
</script>
When load()
is used instead of update()
all the elements will be cleared which don't have a value in the loaded data. This is useful when we load complete set of data and we want to make sure no previous values remain filled.
Formatting Loaded Form Data
We can pass a function to the form's :format-load
option, which transforms any data loaded through load(data, true)
:
<template>
<Vueform ref="form$" :format-load="formatLoadedData">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
import { ref, onMounted } from 'vue'
import axios from 'axios'
export default {
setup(props, context) {
const form$ = ref(null)
const formatLoadedData = (data) => {
return {
name: data.name.toUpperCase(),
email: data.name.toLowerCase(),
}
}
onMounted(async () => {
form$.value.load({
name: 'John Doe',
email: 'john@Doe.com'
}, true) // `true` refers to `format: true` param
})
return { form$ }
}
}
</script>
The loaded value will be:
{
name: 'JOHN DOE',
email: 'john@doe.com'
}
Managing Element Data via API
We can also reach and update an element's data using the Vueform's el$(path)
method:
<template>
<Vueform ref="form$">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup(props, context) {
const form$ = ref(null)
onMounted(() => {
const name = form$.value.el$('name')
const email = form$.value.el$('email')
console.log(name.value) // getting `name` element value
console.log(email.value) // getting `email` element value
name.update('John Doe') // setting `name` element value
email.update('john@doe.com') // setting `email` element value
})
return { form$ }
}
}
</script>
Formatting Loaded Element Data
We can pass a function to the form's :format-load
option, which transforms any data loaded through load(data, true)
:
<template>
<Vueform ref="form$">
<TextElement name="name" label="Name" :format-load="formatLoadedName" />
<TextElement name="email" label="Email" :format-load="formatLoadedEmail" />
</Vueform>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup(props, context) {
const form$ = ref(null)
const formatLoadedName = (value) => {
return value.toUpperCase()
}
const formatLoadedEmail = (value) => {
return value.toLowerCase()
}
onMounted(() => {
form$.value.load({
name: 'John Doe',
email: 'john@Doe.com'
}, true)
})
return { form$ }
},
}
</script>
The loaded value will be:
{
name: 'JOHN DOE',
email: 'john@doe.com'
}
Submitting Form Data
We can tell Vueform where to submit our data by setting endpoint
and method
props:
<template>
<Vueform endpoint="/form/submit" method="post">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
The default values can be configured in vueform.config.js
:
// vueform.config.js
export default {
endpoints: {
submit: {
url: '/form/submit',
method: 'post'
}
}
}
Data vs. Request Data
There are two types of form data the form can submit. One is requestData
that exludes elements with available: false
or submit: false
properties. The available
property is only false
if the element has conditions which are unmet. The submit
property can be set manually for any element to prevent submitting its data. The other one is data
which contains the data of all form elements regardless of the available
and submit
properties.
The form submits the requestData
by default.
In case we'd like to change this and submit the complete form data without any restrictions we can pass a function to the form's :form-data
option that returns the form's data
(instead if requestData
):
<template>
<Vueform :form-data="form$ => form$.convertFormData(form$.data)">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
The convertFormData()
method converts the data object to FormData. This might be left out if you don't want to send multipart/form-data
request.
Formatting Data Before Submit
We can pass a function to :format-data
option of Vueform or any elements, that will format its requestData
:
<template>
<Vueform :format-data="formatFormData">
<TextElement
name="name"
label="Name"
default="John Doe"
:format-data="formatName"
/>
<TextElement
name="email"
label="Email"
default="john@Doe.com"
:format-data="formatEmail"
/>
</Vueform>
</template>
<script>
export default {
mehtods: {
formatFormData({ name, email }) {
return {
name: `<div>${name}</div>`,
email: `<div>${email}</div>`,
}
},
formatName(name, value) {
return { [name]: value.toUpperCase() } // must return an object
},
formatEmail(name, value) {
return { [name]: value.toLowerCase() } // must return an object
}
}
}
</script>
The submitted data will be:
{
name: '<div>JOHN DOE</div>',
email: '<div>john@doe.com</div>'
}
This can be used in conjuction with formatLoad
methods to transform data between databases and forms.
Preparing for Submit
We can pass an async
function to :prepare
option of Vueform, that will be executed before the form submits:
<template>
<Vueform :prepare="prepareForm">
<TextElement name="name" label="Name" />
<TextElement name="email" label="Email" />
</Vueform>
</template>
<script>
export default {
methods: {
async prepareForm(data) {
try {
await // async process
} catch (error) {
throw error // this will cancel the submit process
}
}
}
}
</script>
The prepare
function runs after submit was initiated, the elements are validated and none was found invalid.
The submit process halts until all prepare functions are finished. The submit process can be cancelled by throwing an error in the prepare
function.