Breaking Forms into Steps
Learn how to break you forms into steps to enchance user experience.
Using Form Steps
We can use FormSteps
and FormStep
components to break forms into steps:
<template>
<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>
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref } from 'vue'
const form = ref({
steps: {
first: {
label: 'First',
elements: ['first_input']
},
second: {
label: 'Second',
elements: ['second_input']
},
third: {
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>
<!-- Options API -->
<script>
export default {
data: () => ({
form: {
steps: {
first: {
label: 'First',
elements: ['first_input']
},
second: {
label: 'Second',
elements: ['second_input']
},
third: {
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>
<!-- Composition API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
steps: {
first: {
label: 'First',
elements: ['first_input']
},
second: {
label: 'Second',
elements: ['second_input']
},
third: {
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' },
}
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first: {
label: 'First',
elements: ['first_input']
},
second: {
label: 'Second',
elements: ['second_input']
},
third: {
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>
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 Step Label
Step labels can be passed via default slot or as a string and can contain HTML:
<template>
<FormStep name="first" ...>
<b>I.</b> First
</FormStep>
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref, h, resolveComponent } from 'vue'
const form = ref({
steps: {
first: {
label: '<b>I.</b> First',
elements: ['first_input'],
},
// ...
},
// ...
})
</script>
<!-- Options API -->
<script>
import { h, resolveComponent } from 'vue'
export default {
data: () => ({
forms: {
steps: {
first: {
label: '<b>I.</b> First',
elements: ['first_input'],
},
// ...
},
// ...
}
})
}
</script>
<!-- Composition API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
steps: {
first: {
label: '<b>I.</b> First',
elements: ['first_input'],
},
// ...
},
// ...
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first: {
label: '<b>I.</b> First',
elements: ['first_input'],
},
// ...
},
// ...
}
})
}
</script>
... or they can be Vue components:
<template>
<FormStep name="first" ...>
<AppIcon :icon="['fas', 'id-card']"> First
</FormStep>
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref, h, resolveComponent } from 'vue'
const form = ref({
steps: {
first: {
label: {
props: ['form$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'id-card']
}),
'First',
])
},
elements: ['first_input'],
},
// ...
},
// ...
})
</script>
<!-- Options API -->
<script>
import { h, resolveComponent } from 'vue'
export default {
data: () => ({
forms: {
steps: {
first: {
label: {
props: ['form$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'id-card']
}),
'First',
])
},
elements: ['first_input'],
},
// ...
},
// ...
}
})
}
</script>
<!-- Composition API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
steps: {
first: {
label: {
props: ['form$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'id-card']
}),
'First',
])
},
elements: ['first_input'],
},
// ...
},
// ...
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first: {
label: {
props: ['form$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'id-card']
}),
'First',
])
},
elements: ['first_input'],
},
// ...
},
// ...
}
})
}
</script>
Customizing Steps Controls
We can hide buttons for a step using buttons
option. For example:
<template>
<FormStep name="first" :buttons="{
previous: false
}" ... />
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref } from 'vue'
const form = ref({
steps: {
first: {
label: 'First',
elements: ['first_input'],
buttons: {
previous: false,
}
},
// ...
},
// ...
})
</script>
<!-- Options API -->
<script>
export default {
data: () => ({
forms: {
steps: {
first: {
label: 'First',
elements: ['first_input'],
buttons: {
previous: false,
}
},
// ...
},
// ...
}
})
}
</script>
<!-- Composition API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
steps: {
first: {
label: 'First',
elements: ['first_input'],
buttons: {
previous: false,
}
},
// ...
},
// ...
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first: {
label: 'First',
elements: ['first_input'],
buttons: {
previous: false,
}
},
// ...
},
// ...
}
})
}
</script>
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:
<template>
<FormStep name="first" :labels="{
previous: '< Previous',
next: 'Next >'
}" ... />
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref } from 'vue'
const form = ref({
steps: {
first: {
label: 'First',
elements: ['first_input'],
labels: {
previous: '< Previous',
next: 'Next >'
}
},
// ...
},
// ...
})
</script>
<!-- Options API -->
<script>
export default {
data: () => ({
forms: {
steps: {
first: {
label: 'First',
elements: ['first_input'],
labels: {
previous: '< Previous',
next: 'Next >'
}
},
// ...
},
// ...
}
})
}
</script>
<!-- Composition API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
steps: {
first: {
label: 'First',
elements: ['first_input'],
labels: {
previous: '< Previous',
next: 'Next >'
}
},
// ...
},
// ...
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first: {
label: 'First',
elements: ['first_input'],
labels: {
previous: '< Previous',
next: 'Next >'
}
},
// ...
},
// ...
}
})
}
</script>
Button labels can contain HTML or they can be Vue components:
<template>
<FormStepsControls :labels="false">
<template #previous><icon name='arrow-left' /> Previous</template>
<template #next>Next <icon name='arrow-right' /></template>
<template #finish><icon name='tick' /> Finish</template>
</FormStepsControls>
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref, h, resolveComponent } from 'vue'
const form = ref({
steps: {
first: {
label: 'First',
elements: ['first_input'],
labels: {
previous: {
props: ['step$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'arrow-left']
}),
h('Previous'),
])
},
// ...
}
},
// ...
},
// ...
})
</script>
<!-- Options API -->
<script>
import { h, resolveComponent } from 'vue'
export default {
data: () => ({
forms: {
steps: {
first: {
label: 'First',
elements: ['first_input'],
labels: {
previous: {
props: ['step$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'arrow-left']
}),
h('Previous'),
])
},
// ...
}
},
// ...
},
// ...
}
})
}
</script>
<!-- Composition API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
steps: {
first: {
label: 'First',
elements: ['first_input'],
labels: {
previous: {
props: ['step$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'arrow-left']
}),
h('Previous'),
])
},
// ...
}
},
// ...
},
// ...
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first: {
label: 'First',
elements: ['first_input'],
labels: {
previous: {
props: ['step$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'arrow-left']
}),
h('Previous'),
])
},
// ...
}
},
// ...
},
// ...
}
})
}
</script>
When using slots for custom controls template FormStepsControls
component must receive :labels="false"
option and it will ignore the :labels
object of FormStep
.
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>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
onMounted(() => {
form$.value.steps$ // returns FormSteps component instance
form$.value.steps$.steps$.first // returns FormStep component instance named `first`
})
</script>
<!-- Options API -->
<script>
export default {
mounted() {
this.$refs.form$.steps$ // returns FormSteps component instance
this.$refs.form$.steps$.steps$.first // returns FormStep component instance named `first`
}
}
</script>
<template>
<Vueform v-bind="form" ref="form$" />
</template>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
const form = ref({
steps: {
first: {
label: 'First',
elements: ['first_input']
},
},
// ...
})
onMounted(() => {
form$.value.steps$ // returns FormSteps component instance
form$.value.steps$.steps$.first // returns FormStep component instance named `first`
})
</script>
<!-- Options API -->
<script>
export default {
data: () => ({
steps: {
first: {
label: 'First',
elements: ['first_input']
},
},
// ...
}),
mounted() {
this.$refs.form$.steps$ // returns FormSteps component instance
this.$refs.form$.steps$.steps$.first // returns FormStep component instance named `first`
}
}
</script>
<!-- Composition API -->
<script>
import { ref, onMounted } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
steps: {
first: {
label: 'First',
elements: ['first_input'],
},
},
// ...
})
onMounted(() => {
form.steps$.value // returns FormSteps component instance
form.steps$.value.steps$.first // returns FormStep component instance named `first`
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first: {
label: 'First',
elements: ['first_input'],
},
},
// ...
}
}),
mounted() {
this.steps$ // returns FormSteps component instance
this.steps$.steps$.first // returns FormStep component instance named `first`
}
}
</script>
Alternatively we can use Vueform's @mounted
event to access steps$
:
<template>
<Vueform @mounted="(form$) => {
form$.steps$ // returns FormSteps component instance
form$.steps$.steps$.first // returns FormStep component instance named `first`
}">
<template #empty>
<FormSteps>
<FormStep name="first" ... />
</FormSteps>
</template>
</Vueform>
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
const form = ref({
steps: {
first: {
label: 'First',
elements: ['first_input']
},
},
onMounted(form$) {
form$.steps$ // returns FormSteps component instance
form$.steps$.steps$.first // returns FormStep component instance named `first`
}
// ...
})
</script>
<!-- Options API -->
<script>
export default {
data: () => ({
steps: {
first: {
label: 'First',
elements: ['first_input']
},
},
onMounted(form$) {
form$.steps$ // returns FormSteps component instance
form$.steps$.steps$.first // returns FormStep component instance named `first`
}
// ...
}),
}
</script>
<!-- Composition API -->
<script>
import { ref, onMounted } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
steps: {
first: {
label: 'First',
elements: ['first_input'],
},
},
onMounted(form$) {
form$.steps$ // returns FormSteps component instance
form$.steps$.steps$.first // returns FormStep component instance named `first`
}
// ...
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first: {
label: 'First',
elements: ['first_input'],
},
},
onMounted(form$) {
form$.steps$ // returns FormSteps component instance
form$.steps$.steps$.first // returns FormStep component instance named `first`
},
// ...
}
}),
}
</script>
Later we can use check out FormSteps
and FormStep
component reference to see what method and properties can be used.
Subscribing To Step Events
We can subscribe to FormSteps
events like @next
or @previous
and FormStep
event like @activate
or @complete
via Vueform's steps$
property:
<template>
<Vueform ref="form$">
<template #empty>
<FormSteps>
<FormStep name="first" ... />
</FormSteps>
</template>
</Vueform>
</template>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
onMounted(() => {
// Subscribe to FormSteps' @next event
form$.value.steps$.on('next', (step$) => {
// ...
})
// Subscribe to `first` FormStep's @activate event
form$.value.steps$.steps$.first.on('activate', (step$) => {
// ...
})
})
</script>
<!-- Options API -->
<script>
export default {
mounted() {
// Subscribe to FormSteps' @next event
this.$refs.form$.steps$.on('next', (step$) => {
// ...
})
// Subscribe to `first` FormStep's @activate event
this.$refs.form$.steps$.steps$.first.on('activate', (step$) => {
// ...
})
}
}
</script>
<template>
<Vueform v-bind="form" ref="form$" />
</template>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
const form = ref({
steps: {
first: {
label: 'First',
elements: ['first_input']
},
},
// ...
})
onMounted(() => {
// Subscribe to FormSteps' @next event
form$.value.steps$.on('next', (step$) => {
// ...
})
// Subscribe to `first` FormStep's @activate event
form$.value.steps$.steps$.first.on('activate', (step$) => {
// ...
})
})
</script>
<!-- Options API -->
<script>
export default {
data: () => ({
steps: {
first: {
label: 'First',
elements: ['first_input']
},
},
// ...
}),
mounted() {
// Subscribe to FormSteps' @next event
this.$refs.form$.steps$.on('next', (step$) => {
// ...
})
// Subscribe to `first` FormStep's @activate event
this.$refs.form$.steps$.steps$.first.on('activate', (step$) => {
// ...
})
}
}
</script>
<!-- Composition API -->
<script>
import { ref, onMounted } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
steps: {
first: {
label: 'First',
elements: ['first_input'],
},
},
// ...
})
onMounted(() => {
// Subscribe to FormSteps' @next event
form.steps$.value.on('next', (step$) => {
// ...
})
// Subscribe to `first` FormStep's @activate event
form.steps$.value.steps$.first.on('activate', (step$) => {
// ...
})
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
steps: {
first: {
label: 'First',
elements: ['first_input'],
},
},
// ...
}
}),
mounted() {
// Subscribe to FormSteps' @next event
this.steps$.on('next', (step$) => {
// ...
})
// Subscribe to `first` FormStep's @activate event
this.steps$.steps$.first.on('activate', (step$) => {
// ...
})
}
}
</script>
Using Tabs
Tabs 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:
<template>
<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>
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref } from 'vue'
const form = ref({
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
second: {
label: 'Second',
elements: ['second_input']
},
third: {
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>
<!-- Options API -->
<script>
export default {
data: () => ({
form: {
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
second: {
label: 'Second',
elements: ['second_input']
},
third: {
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>
<!-- Composition API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
second: {
label: 'Second',
elements: ['second_input']
},
third: {
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' },
}
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
second: {
label: 'Second',
elements: ['second_input']
},
third: {
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>
Tab Options
Each FormTab
component must have at least 2 props:
name
- the internal name of the tab we can later use to reach its APIelements
- an array of element names (as string) that the tab should include.
And also label
, which is the label visible to the user if it is not defined inline between <FormTab></FormTab>
.
Customizing Tab Label
Tab labels can be passed via default slot or as a string and can contain HTML:
<template>
<FormTab name="first" ...>
<b>I.</b> First
</FormTab>
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref, h, resolveComponent } from 'vue'
const form = ref({
tabs: {
first: {
label: '<b>I.</b> First',
elements: ['first_input'],
},
// ...
},
// ...
})
</script>
<!-- Options API -->
<script>
import { h, resolveComponent } from 'vue'
export default {
data: () => ({
forms: {
tabs: {
first: {
label: '<b>I.</b> First',
elements: ['first_input'],
},
// ...
},
// ...
}
})
}
</script>
<!-- Composition API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
tabs: {
first: {
label: '<b>I.</b> First',
elements: ['first_input'],
},
// ...
},
// ...
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
tabs: {
first: {
label: '<b>I.</b> First',
elements: ['first_input'],
},
// ...
},
// ...
}
})
}
</script>
... or they can be Vue components:
<template>
<FormTab name="first" ...>
<AppIcon :icon="['fas', 'id-card']"> First
</FormTab>
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref, h, resolveComponent } from 'vue'
const form = ref({
tabs: {
first: {
label: {
props: ['form$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'id-card']
}),
'First',
])
},
elements: ['first_input'],
},
// ...
},
// ...
})
</script>
<!-- Options API -->
<script>
import { h, resolveComponent } from 'vue'
export default {
data: () => ({
forms: {
tabs: {
first: {
label: {
props: ['form$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'id-card']
}),
'First',
])
},
elements: ['first_input'],
},
// ...
},
// ...
}
})
}
</script>
<!-- Composition API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
tabs: {
first: {
label: {
props: ['form$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'id-card']
}),
'First',
])
},
elements: ['first_input'],
},
// ...
},
// ...
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref, h, resolveComponent } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
tabs: {
first: {
label: {
props: ['form$'],
render: () => h('span', [
h(resolveComponent('AppIcon'), {
icon: ['far', 'id-card']
}),
'First',
])
},
elements: ['first_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>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
onMounted(() => {
form$.value.tabs$ // returns FormTabs component instance
form$.value.tabs$.tabs$.first // returns FormTab component instance named `first`
})
</script>
<!-- Options API -->
<script>
export default {
mounted() {
this.$refs.form$.tabs$ // returns FormTabs component instance
this.$refs.form$.tabs$.tabs$.first // returns FormTab component instance named `first`
}
}
</script>
<template>
<Vueform v-bind="form" ref="form$" />
</template>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
const form = ref({
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
},
// ...
})
onMounted(() => {
form$.value.tabs$ // returns FormTabs component instance
form$.value.tabs$.tabs$.first // returns FormTab component instance named `first`
})
</script>
<!-- Options API -->
<script>
export default {
data: () => ({
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
},
// ...
}),
mounted() {
this.$refs.form$.tabs$ // returns FormTabs component instance
this.$refs.form$.tabs$.tabs$.first // returns FormTab component instance named `first`
}
}
</script>
<!-- Composition API -->
<script>
import { ref, onMounted } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
tabs: {
first: {
label: 'First',
elements: ['first_input'],
},
},
// ...
})
onMounted(() => {
form.tabs$.value // returns FormTabs component instance
form.tabs$.value.tabs$.first // returns FormTab component instance named `first`
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
tabs: {
first: {
label: 'First',
elements: ['first_input'],
},
},
// ...
}
}),
mounted() {
this.tabs$ // returns FormTabs component instance
this.tabs$.tabs$.first // returns FormTab component instance named `first`
}
}
</script>
Alternatively we can use Vueform's @mounted
event to access tabs$
:
<template>
<Vueform @mounted="(form$) => {
form$.tabs$ // returns FormTabs component instance
form$.tabs$.tabs$.first // returns FormTab component instance named `first`
}">
<template #empty>
<FormTabs>
<FormTab name="first" ... />
</FormTabs>
</template>
</Vueform>
</template>
<template>
<Vueform v-bind="form" />
</template>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
const form = ref({
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
},
onMounted(form$) {
form$.tabs$ // returns FormTabs component instance
form$.tabs$.tabs$.first // returns FormTab component instance named `first`
}
// ...
})
</script>
<!-- Options API -->
<script>
export default {
data: () => ({
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
},
onMounted(form$) {
form$.tabs$ // returns FormTabs component instance
form$.tabs$.tabs$.first // returns FormTab component instance named `first`
}
// ...
}),
}
</script>
<!-- Composition API -->
<script>
import { ref, onMounted } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
tabs: {
first: {
label: 'First',
elements: ['first_input'],
},
},
onMounted(form$) {
form$.tabs$ // returns FormTabs component instance
form$.tabs$.tabs$.first // returns FormTab component instance named `first`
}
// ...
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
tabs: {
first: {
label: 'First',
elements: ['first_input'],
},
},
onMounted(form$) {
form$.tabs$ // returns FormTabs component instance
form$.tabs$.tabs$.first // returns FormTab component instance named `first`
},
// ...
}
}),
}
</script>
Later we can use check out FormTabs
and FormTab
component reference to see what method and properties can be used.
Subscribing To Tab Events
We can subscribe to FormTabs
events like @select
and FormTab
event like @activate
or @inactivate
via Vueform's tabs$
property:
<template>
<Vueform ref="form$">
<template #empty>
<FormTabs>
<FormTab name="first" ... />
</FormTabs>
</template>
</Vueform>
</template>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
onMounted(() => {
// Subscribe to FormTabs' @select event
form$.value.tabs$.on('select', (currentTab$, previousTab$) => {
// ...
})
// Subscribe to `first` FormTab's @activate event
form$.value.tabs$.tabs$.first.on('activate', (tab$) => {
// ...
})
})
</script>
<!-- Options API -->
<script>
export default {
mounted() {
// Subscribe to FormTabs' @select event
this.$refs.form$.tabs$.on('select', (currentTab$, previousTab$) => {
// ...
})
// Subscribe to `first` FormTab's @activate event
this.$refs.form$.tabs$.tabs$.first.on('activate', (tab$) => {
// ...
})
}
}
</script>
<template>
<Vueform v-bind="form" ref="form$" />
</template>
<!-- Composition API -->
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
const form = ref({
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
},
// ...
})
onMounted(() => {
// Subscribe to FormTabs' @select event
form$.value.tabs$.on('select', (currentTab$, previousTab$) => {
// ...
})
// Subscribe to `first` FormTab's @activate event
form$.value.tabs$.tabs$.first.on('activate', (tab$) => {
// ...
})
})
</script>
<!-- Options API -->
<script>
export default {
data: () => ({
tabs: {
first: {
label: 'First',
elements: ['first_input']
},
},
// ...
}),
mounted() {
// Subscribe to FormTabs' @select event
this.$refs.form$.tabs$.on('select', (currentTab$, previousTab$) => {
// ...
})
// Subscribe to `first` FormTab's @activate event
this.$refs.form$.tabs$.tabs$.first.on('activate', (tab$) => {
// ...
})
}
}
</script>
<!-- Composition API -->
<script>
import { ref, onMounted } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: (props, context) => {
const form = useVueform(props, context)
const vueform = ref({
tabs: {
first: {
label: 'First',
elements: ['first_input'],
},
},
// ...
})
onMounted(() => {
// Subscribe to FormTabs' @select event
form.tabs$.value.on('select', (currentTab$, previousTab$) => {
// ...
})
// Subscribe to `first` FormTab's @activate event
form.tabs$.value.tabs$.first.on('activate', (tab$) => {
// ...
})
})
return {
...form,
vueform,
}
}
}
</script>
<!-- Options API -->
<script>
import { ref } from 'vue'
import { Vueform, useVueform } from '@vueform/vueform'
export default {
mixins: [Vueform],
setup: useVueform,
data: () => ({
vueform: {
tabs: {
first: {
label: 'First',
elements: ['first_input'],
},
},
// ...
}
}),
mounted() {
// Subscribe to FormTabs' @select event
this.tabs$.on('select', (currentTab$, previousTab$) => {
// ...
})
// Subscribe to `first` FormTab's @activate event
this.tabs$.tabs$.first.on('activate', (tab$) => {
// ...
})
}
}
</script>