Vue Form Wizard 2
A dynamic form wizard to split your forms easier
Vue-form-wizard is a vue based component with no external depenendcies which simplifies tab wizard management and allows you to focus on the functional part of your app rather than wasting time on details. Just forget about id's, external scripts and jQuery dependencies
Usage
NPM
npm install @orbica/vue-form-wizard-2
Component registration
//global registration
import VueFormWizard from 'vue-form-wizard'
import 'vue-form-wizard/dist/vue-form-wizard.min.css'
Vue.use(VueFormWizard)
//local registration
import {FormWizard, TabContent} from 'vue-form-wizard'
import 'vue-form-wizard/dist/vue-form-wizard.min.css'
//component code
components: {
FormWizard,
TabContent
}
Template usage
<form-wizard>
<tab-content title="Personal details">
My first tab content
</tab-content>
<tab-content title="Additional Info">
My second tab content
</tab-content>
<tab-content title="Last step">
Yuhuuu! This seems pretty damn simple
</tab-content>
</form-wizard>
Deploy to NPM
- Once merged into master, run
npm version <new version>
locally. -
<new version>
can be a version number or one of major, minor, patch or other - This will update the version number in the package.json then push to Git automatically
- The gitlab-ci will then run the tests and deploy to NPM when they pass
Compatibility
Vue-form-wizard works with Vue > 2.2, but the examples in the docs follow the latest Vue > 2.5 changes especially on the slot
parts.
If you use vue < 2.5.x, use scope="props"
instead of slot-scope="props"
for scoped slots. See Vue 2.5 simplified scoped slots
Props
Form Wizard props
props: {
title: {
type: String,
default: ''
},
subtitle: {
type: String,
default: ''
},
nextButtonText: {
type: String,
default: 'Next'
},
backButtonText: {
type: String,
default: 'Back'
},
finishButtonText: {
type: String,
default: 'Finish'
},
hideButtons: {
type: Boolean,
default: false
},
validateOnBack: Boolean,
disableBackNavigation: {
type: Boolean,
default: false
},
color: {
// Applies to text, border and circle
type: String,
default: '#e74c3c'
},
errorColor: {
type: String,
default: '#8b0000'
},
shape: {
type: String,
default: 'circle'
},
layout: {
type: String,
default: 'horizontal'
},
stepsClasses: {
type: [String, Array],
default: ''
},
stepSize: {
type: String,
default: 'md',
validator: (value) => {
let acceptedValues = ['xs', 'sm', 'md', 'lg']
return acceptedValues.indexOf(value) !== -1
}
},
transition: {
// Name of the transition when transition between steps
type: String,
default: ''
},
startIndex: {
// Index of the initial tab to display
type: Number,
default: 0,
validator: (value) => {
return value >= 0
}
},
customRightButtonText: {
type: String,
default: ''
},
customLeftButtonText: {
type: String,
default: ''
},
loadingIcon: {
type: String,
default: ''
},
loading: {
// Supports .sync
type: Boolean,
default: undefined
}
},
Tab content props
props: {
title: {
type: String,
default: ''
},
icon: {
// Icon name for the upper circle corresponding to the tab
type: String,
default: ''
},
beforeChange: {
// Function to execute before tab switch. Return value must be boolean
// If the return result is false, tab switch is restricted
type: Function
},
afterChange: {
// Function to execute after tab switch. Return void for now.
// Safe to assume necessary validation has already occurred
type: Function
},
route: {
type: [String, Object]
},
additionalInfo: {
type: Object,
default: () => {}
}
},
Events
Vue-form-wizard emits certain events when certain actions happen inside the component. The events can be noticed in some of the demos and especially in the async validation demo
-
on-complete Called when the finish button is clicked and the
before-change
for the last step (if present) was executed. No params are sent together with this event.this.$emit('on-complete')
-
on-loading Called whenever an async
before-change
is executed. This event is emitted before executingbefore-change
and after finishing execution ofbefore-change
method.on-loading
is emitted together with a Boolean value.this.$emit('on-loading', value)
-
on-validate Called whenever the execution of a
before-change
method is completed. The event sends along a Boolean which represents the validation result as well as an int with te tab index.this.$emit('on-validate', validationResult, this.activeTabIndex)
-
on-error Called when
before-change
is a promised and is rejected with a message. The message is passed alongthis.$emit('on-error', error)
See async validation fiddle -
on-change Called upon step changes. Has prevIndex and nextIndes as params.
this.$emit('on-change', prevIndex, nextIndex)
-
on-custom-left and on-custom-right Called when custom-left and custom-right slots are clicked
<span @click="$emit('on-custom-left')">
-
active and inactive Emitted by
tab-content
when active state of tab changesthis.$emit(newValue ? 'active' : 'inactive')
Slots
- Default - Used for tab-contents
- title - Upper title section including sub-title
- prev - Previous button content (no need to worry about handling the button functionality)
- next - Next button content
- finish - Finish button content
- custom-buttons-left - Appears on right of "Back" button
- custom-buttons-right - Appears on the left of "Next/Finish" button
Methods
By using refs on the form-wizard
component, you can access some internal wizard properties and methods.
Some of them are intended for internal usage while others can be used for general purpose operations.
- reset - will reset the wizard to the initial state
- activateAll - will activate all steps as if the user went through all
- nextTab - navigates to the next tab. The same method is used when clicking next button
- prevTab - navigates to the prev tab. The same method is used when clicking prev button
- changeTab(oldIndex, newIndex) - Navigates from one tab to another. Note that this method does not trigger validation methods. Use it with caution!
!> It's advised to use only the methods above, since the methods which are not listed here are internal and might change or get removed over time.
Scoped slots
Form-wizard exposes multiple scoped slots which can be used to customize some parts of the wizard.
- nextTab // will go to the next tab/step when called
- prevTab //will got to the prev tab/step when called
- activeTabIndex // current active tab index
- isLastStep // boolean to tell whether it's the last step or not
- fillButtonStyle // object with styles for wizard-buttons (contains background and color passed through wizard props)
These properties apply to the following slots:
- prev - Previous button content (no need to worry about handling the button functionality)
- next - Next button content
- finish - Finish button content
- custom-buttons-left - Appears on right of "Back" button
- custom-buttons-right - Appears on the left of "Next/Finish" button
Footer slot
The footer slot would be usually used to replace the whole content of your footer. By default it contains the wizard buttons (back, next, finish).
When using this slot, those buttons are replaced with your own content. You can achieve the same default wizard functionality and event tweak it with the help of the exposed methods/properties from slot props
Note that using this slot, means that you have to handle some of the wizard logic through the exposed methods/properties defined above and your template might get more verbose. If you need very fine customizations and more control over the wizard button actions, then you could use this slot. Otherwise, you could stick with the buttons slots as they can be used as scoped slots as well. One potential usage can be that you want to have a different button when completing the wizard. Maybe you want to position it in the center, give it a different color and click event
<template slot="footer" slot-scope="props">
<div class="wizard-footer-left">
<wizard-button v-if="props.activeTabIndex > 0 && !props.isLastStep" @click.native="props.prevTab()" :style="props.fillButtonStyle">Previous</wizard-button>
</div>
<div class="wizard-footer-right">
<wizard-button v-if="!props.isLastStep"@click.native="props.nextTab()" class="wizard-footer-right" :style="props.fillButtonStyle">Next</wizard-button>
<wizard-button v-else @click.native="alert('Done')" class="wizard-footer-right finish-button" :style="props.fillButtonStyle"> {{props.isLastStep ? 'Done' : 'Next'}}</wizard-button>
</div>
</template>
This is just one example. You can add more buttons, hide or display conditionally based on the exposed properties. Working fiddle for the example above
Step slot
This slot can be used to disable the click event on the step or to customize the UI of each step One possible usage:
<wizard-step
slot-scope="props"
slot="step"
:tab="props.tab"
:transition="props.transition"
:index="props.index">
</wizard-step>
step
slot
Exposed props for the - tab (the tab object which contains the tab-content component corresponding to the step) This object contains several fields such as
active, checked, shape, color
and so on. You can check how these are used here: - index (The index of the step)
- transition (Transition prop passed from form-wizard)