Breaking Forms into Steps
Learn how to break you forms into steps to enchance user experience.
Using Inline Form Steps
We can use FormSteps
and FormStep
components to break forms into steps:
<Vueform>
<template #empty>
<FormSteps>
<FormStep name="first" label="First" :elements="['first_input']" />
<FormStep name="second" label="Second" :elements="['second_input']" />
<FormStep name="third" label="Third" :elements="['third_input']" />
</FormSteps>
<FormElements>
<TextElement name="first_input" placeholder="First input" />
<TextElement name="second_input" placeholder="Second input" />
<TextElement name="third_input" placeholder="Third input" />
</FormElements>
<FormStepsControls />
</template>
</Vueform>
When using them inline we have to put all the content of the form into #empty
slot, becase the default Vueform slots is only intended for rendering elements.
Form elements have to be put into FormElements
component which serves as a wrapper.
We also need to add FormStepsControls
to the template, which renders the form controls (Previous, Next, Finish).
We can use these three parts anywhere in out template, which gives us the freedom to create any kind of layout we want.
Step Options
Each FormStep
component must have at least 2 props:
name
- the internal name of the step we can later use to reach its APIelements
- an array of element names (as string) that the step should include.
And also label
, which is the label visible to the user if it is not defined inline between <FormStep></FormStep>
.
Customizing Steps Controls
We can hide buttons for a step using buttons
option. For example:
<FormStep name="first" :buttons="{
previous: false
}" ... />
This will hide the previous button on the first step. We can also hide next
and finish
buttons.
We can also change the labels of buttons for a step using labels
options. For example:
<FormStep name="first" :labels="{
previous: '< Previous',
next: 'Next >'
}" ... />
Button labels can contain HTML or they can be Vue components:
<FormStep name="first" :labels="{
previous: { template: `<span><icon name='arrow-left' /> Previous</span>` },
next: { template: `<span>Next <icon name='arrow-right' /></span>` },
}" ... />
We can provide default control templates to FormStepsControls
via slots:
<FormStepsControls :labels="false">
<slot #previous><icon name='arrow-left' /> Previous</slot>
<slot #next>Next <icon name='arrow-right' /></slot>
<slot #finish><icon name='tick' /> Finish</slot>
</FormStepsControls>
When using slots for custom controls template FormStepsControls
component must receive :labels="false"
option and it will ignore the :labels
object of FormStep
.
Using Form Steps as an Object
If we are using objects to describe our forms we can use steps
option to create a configuration for form steps:
<script>
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first_step: {
label: 'First',
elements: ['first_input']
},
second_step: {
label: 'Second',
elements: ['second_input']
},
third_step: {
label: 'Third',
elements: ['third_input']
},
},
schema: {
first_input: { type: 'text', placeholder: 'First input' },
second_input: { type: 'text', placeholder: 'Second input' },
third_input: { type: 'text', placeholder: 'third input' },
}
}
})
}
</script>
Steps API
Once we have steps we can reach their API and use their methods and properties.
This is how we can reach FormSteps
and FormStep
components:
<template>
<Vueform ref="form$">
<template #empty>
<FormSteps>
<FormStep name="first" ... />
</FormSteps>
<!-- ... -->
</template>
</Vueform>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup(props, context) {
const form$ = ref(null)
form$.value.steps$ // returns FormSteps component instance
form$.value.steps$.steps$.first // returns FormStep component instance named `first`
return { form$ }
}
}
</script>
<script>
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first_input: {
// ...
},
},
// ...
}
}),
mounted() {
this.steps$ // returns FormSteps component instance
this.steps$.steps$.first // returns FormStep component instance named `first`
}
</script>
Later we can use consult FormSteps
and FormStep
API Reference to see what method and properties can be used.
Using Tabs
Steps are useful for users to submit data in a more user friendly way, but it's less convenient for changing existing data. If we'd like to load existing data which was initially submitted via steps, we can use FormTabs
and FormTab
components to replace steps:
<Vueform>
<template #empty>
<FormTabs>
<FormTab name="first" label="First" :elements="['first_input']" />
<FormTab name="second" label="Second" :elements="['second_input']" />
<FormTab name="third" label="Third" :elements="['third_input']" />
</FormTabs>
<FormElements>
<TextElement name="first_input" placeholder="First input" />
<TextElement name="second_input" placeholder="Second input" />
<TextElement name="third_input" placeholder="Third input" />
</FormElements>
</template>
</Vueform>
Tabs can also be used as an object, just like steps:
<script>
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
tabs: {
first_input: {
label: 'First',
elements: ['first']
},
second_input: {
label: 'Second',
elements: ['second']
},
third_input: {
label: 'Third',
elements: ['third']
},
},
schema: {
first_input: { type: 'text', placeholder: 'First input' },
second_input: { type: 'text', placeholder: 'Second input' },
third_input: { type: 'text', placeholder: 'third input' },
}
}
})
}
</script>
Tabs API
We can also reach FormTabs
and FormTab
components' API once they are mounted:
<template>
<Vueform ref="form$">
<template #empty>
<FormTabs>
<FormTab name="first" ... />
</FormTabs>
<!-- ... -->
</template>
</Vueform>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup(props, context) {
const form$ = ref(null)
form$.value.tabs$ // returns FormTabs component instance
form$.value.tabs$.tabs$.first // returns FormTab component instance named `first`
return { form$ }
}
}
</script>
<script>
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
tabs: {
first_input: {
// ...
},
},
// ...
}
}),
mounted() {
this.tabs$ // returns FormTabs component instance
this.tabs$.tabs$.first // returns FormTab component instance named `first`
}
</script>
Later we can use consult FormTabs
and FormTab
API Reference to see what method and properties can be used.