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 vue-form-wizard
Direct script include
Download the css and js files from dist folder or reference them directly from github (check jsfiddle links)
<link rel="stylesheet" href="https://unpkg.com/vue-form-wizard/dist/vue-form-wizard.min.css">
<script src="https://unpkg.com/vue-form-wizard/dist/vue-form-wizard.js"></script>
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>
Props
Form Wizard props
props: {
title: {
type: String,
default: 'Awesome Wizard'
},
subtitle: {
type: String,
default: 'Split a complicated flow in multiple steps'
},
nextButtonText: {
type: String,
default: 'Next'
},
backButtonText: {
type: String,
default: 'Back'
},
finishButtonText: {
type: String,
default: 'Finish'
},
/***
* Sets validation (on/off) for back button. By default back button ignores validation
*/
validateOnBack: Boolean,
/***
* Applies to text, border and circle
*/
color: {
type: String,
default: '#e74c3c' //circle, border and text color
},
/***
* Is set to current step and text when beforeChange function fails
*/
errorColor: {
type: String,
default: '#8b0000'
},
/**
* Can take one of the following values: 'circle|square|tab`
*/
shape: {
type: String,
default: 'circle'
},
/**
* name of the transition when transition between steps
*/
transition: {
type: String,
default: '' //name of the transition when transition between steps
},
/***
* Index of the initial tab to display
*/
startIndex: {
type: Number,
default: 0
}
}
Tab content props
props: {
title: {
type: String,
default: ''
},
/***
* Icon name for the upper circle corresponding to the tab
* Supports themify icons only for now.
*/
icon: {
type: String,
default: ''
},
/***
* Function to execute before tab switch. Return value must be boolean
* If the return result is false, tab switch is restricted
*/
beforeChange: {
type: Function
}
}
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-changefor 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-changeis executed. This event is emitted before executingbefore-changeand after finishing execution ofbefore-changemethod.on-loadingis emitted together with a Boolean value.this.$emit('on-loading', value) - on-validate Called whenever the execution of a
before-changemethod 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-changeis a promised and is rejected with a message. The message is passed alongthis.$emit('on-error', error)See async validation fiddle
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
Scoped slots
Form-wizard exposes multiple scoped slots which can be used to customize some parts of the wizard. Usage example and implementation details are presented in 0.6.2 release
Since 0.6.4, button slots can be also used as scoped slots and have the following methods/properties exposed
- 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" scope="props">
<div class=wizard-footer-left>
<wizard-button v-if="props.activeTabIndex > 0 && !props.isLastStep" :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:
<template slot="step" scope="props">
<wizard-step :tab="props.tab"
:transition="props.transition"
:index="props.index">
</wizard-step>
</template>
Exposed props for the step slot
- tab (the tab object which contains the tab-content component corresponding to the step) This object contains several fields such as
active, checked, shape, colorand so on. You can check how these are used here: - index (The index of the step)
- transition (Transition prop passed from form-wizard)
Fiddle example You can notice that steps are not longer clickable.
Demos
Basic demo
Other demos:
- Squared steps
- Tabbed steps
- Step index Start at any step. Note: start-index is zero-based and the count starts at 0
- Custom button and title text
- Custom title slot
- Call a function before tab switch
- Complete form example integrated with vue-form-generator
- Element UI form integration
- Vue router integration You can place a
router-viewinside the wizard and have a separate page per tab. Arouteprop must be passed to the tabs you want to handle certain tabs - Async validation with error message
before-changeprop can accept a promise that is resolved withtruewhich will execute the promise before switching to another step/tab (NOTE: This feature is not present in the npm package yet) - Customized buttons with scoped slot
Playground
Simple
<script v-pre type="text/x-template" id="simpledemo"> My first tab content My second tab content Yuhuuu! This seems pretty damn simple <script> Vue.use(VueFormWizard) export default { methods: { onComplete: function(){ alert('Yay. Done!'); } } } </script></script>
Square steps
<script v-pre type="text/x-template" id="squaredsteps"> My first tab content My second tab content Yuhuuu! This seems pretty damn simple <script> Vue.use(VueFormWizard) export default { methods: { onComplete: function(){ alert('Yay. Done!'); } } } </script></script>
Tabbed steps
<script v-pre type="text/x-template" id="tabbedsteps"> My first tab content My second tab content Yuhuuu! This seems pretty damn simple <script> Vue.use(VueFormWizard) export default { methods: { onComplete: function(){ alert('Yay. Done!'); } } } </script></script>
Start from a specific index
<script v-pre type="text/x-template" id="startindex"> My first tab content My second tab content Yuhuuu! This seems pretty damn simple <script> Vue.use(VueFormWizard) export default { methods: { onComplete: function(){ alert('Yay. Done!'); } } } </script></script>
Custom button and title text
<script v-pre type="text/x-template" id="customtext"> My first tab content My second tab content Yuhuuu! This seems pretty damn simple <script> Vue.use(VueFormWizard) export default { methods: { onComplete: function(){ alert('Yay. Done!'); } } } </script></script>
Customize buttons with footer slot
<script v-pre type="text/x-template" id="customslots">This will replace my whole title
My first tab content My second tab content Yuhuuu! This seems pretty damn simple</script>
Call a function before tab switch
<script v-pre type="text/x-template" id="callfunction"> My first tab content My second tab content Yuhuuu! This seems pretty damn simple <script> Vue.use(VueFormWizard) export default { methods: { onComplete: function(){ alert('Yay. Done!'); }, beforeTabSwitch: function(){ alert("This is called before switchind tabs") return true; } }, } </script></script>
Async validation
<script v-pre type="text/x-template" id="asyncvalidation"> First tab Second tab Third tab</script>
Element UI integration
<script v-pre type="text/x-template" id="elementui"> Second tab Yuhuuu! This seems pretty damn simple Back Next Finish <script> Vue.use(VueFormWizard) export default { data() { return { formInline: { user: '', region: '' }, rules: { user: [{ required: true, message: 'Please input Activity name', trigger: 'blur' }, { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' }], region: [{ required: true, message: 'Please select Activity zone', trigger: 'change' }], } } }, methods: { onComplete: function() { alert('Yay. Done!'); }, validateFirstStep() { return new Promise((resolve, reject) => { this.$refs.ruleForm.validate((valid) => { resolve(valid); }); }) } } } </script></script>
Contribution
- Fork the repo
- run
npm install npm run devfor launching the dev example- After making your changes make sure to pull the changes from the source repo to avoid conflicts
npm run buildto generate the new js and css bundles- Commit your changes + the js and css bundles so it's easy to test them right away in fiddles, codepen etc
- Open a Pull Request. For more information refer to github forking workflow