mirror of
https://github.com/tenrok/vue-form-wizard.git
synced 2026-06-23 05:50:33 +03:00
#29 Extract wizard step into separate component and expose via scoped slot
This commit is contained in:
+9
-7
@@ -10,6 +10,15 @@
|
|||||||
@on-loading="setLoading"
|
@on-loading="setLoading"
|
||||||
@on-error="setError"
|
@on-error="setError"
|
||||||
class="card" ref="wizard">
|
class="card" ref="wizard">
|
||||||
|
<template slot="step" scope="props">
|
||||||
|
<wizard-step :tab="props.tab"
|
||||||
|
@click.native="props.navigateToTab(props.index)"
|
||||||
|
:transition="props.transition"
|
||||||
|
:key="props.tab.title"
|
||||||
|
:index="props.index">
|
||||||
|
</wizard-step>
|
||||||
|
</template>
|
||||||
|
|
||||||
<tab-content title="Personal details" icon="ti-user">
|
<tab-content title="Personal details" icon="ti-user">
|
||||||
My first tab
|
My first tab
|
||||||
</tab-content>
|
</tab-content>
|
||||||
@@ -20,13 +29,6 @@
|
|||||||
<div v-if="error">
|
<div v-if="error">
|
||||||
{{error}}
|
{{error}}
|
||||||
</div>
|
</div>
|
||||||
<template slot="footer" scope="props">
|
|
||||||
<div class="wizard-footer-right">
|
|
||||||
<wizard-button :style="props.fillButtonStyle">Cancel</wizard-button>
|
|
||||||
<wizard-button @click.native="props.nextTab()" class="wizard-footer-right" :style="props.fillButtonStyle">Next</wizard-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
</form-wizard>
|
</form-wizard>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -12,31 +12,18 @@
|
|||||||
:style="progressBarStyle"></div>
|
:style="progressBarStyle"></div>
|
||||||
</div>
|
</div>
|
||||||
<ul class="wizard-nav wizard-nav-pills">
|
<ul class="wizard-nav wizard-nav-pills">
|
||||||
<li v-for="(tab, index) in tabs" :class="{active:tab.active}">
|
<slot name="step" v-for="(tab, index) in tabs"
|
||||||
<a href="" @click.prevent="navigateToTab(index)">
|
:tab="tab"
|
||||||
<div class="wizard-icon-circle"
|
:index="index"
|
||||||
:class="{checked:isChecked(index),square_shape:isStepSquare, tab_shape:isTabShape}"
|
:navigate-to-tab="navigateToTab"
|
||||||
:style="[isChecked(index)? stepCheckedStyle : {}, tab.validationError ? errorStyle : {}]">
|
:transition="transition">
|
||||||
|
<wizard-step :tab="tab"
|
||||||
<transition :name="transition" mode="out-in">
|
@click.native="navigateToTab(index)"
|
||||||
<div v-if="tab.active" class="wizard-icon-container"
|
:transition="transition"
|
||||||
:class="{square_shape:isStepSquare, tab_shape:isTabShape}"
|
:key="tab.title"
|
||||||
:style="[tab.active ? iconActiveStyle: {}, tab.validationError ? errorStyle : {}]">
|
:index="index">
|
||||||
<i v-if="tab.icon" :class="tab.icon" class="wizard-icon"></i>
|
</wizard-step>
|
||||||
<i v-else class="wizard-icon">{{index + 1}}</i>
|
</slot>
|
||||||
</div>
|
|
||||||
<i v-if="!tab.active && tab.icon" :class="tab.icon" class="wizard-icon"></i>
|
|
||||||
<i v-if="!tab.active && !tab.icon" class="wizard-icon">{{index + 1}}</i>
|
|
||||||
</transition>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<span class="stepTitle"
|
|
||||||
:class="{active:tab.active, has_error:tab.validationError}"
|
|
||||||
:style="tab.active ? stepTitleStyle : {}">
|
|
||||||
{{tab.title}}
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<div class="wizard-tab-content">
|
<div class="wizard-tab-content">
|
||||||
<slot>
|
<slot>
|
||||||
@@ -89,10 +76,12 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import WizardButton from './WizardButton.vue'
|
import WizardButton from './WizardButton.vue'
|
||||||
|
import WizardStep from './WizardStep.vue'
|
||||||
export default{
|
export default{
|
||||||
name: 'form-wizard',
|
name: 'form-wizard',
|
||||||
components: {
|
components: {
|
||||||
WizardButton
|
WizardButton,
|
||||||
|
WizardStep
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
title: {
|
title: {
|
||||||
@@ -181,34 +170,6 @@
|
|||||||
color: this.color
|
color: this.color
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
iconActiveStyle () {
|
|
||||||
return {
|
|
||||||
backgroundColor: this.color
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stepCheckedStyle () {
|
|
||||||
return {
|
|
||||||
borderColor: this.color
|
|
||||||
}
|
|
||||||
},
|
|
||||||
errorStyle () {
|
|
||||||
return {
|
|
||||||
borderColor: this.errorColor,
|
|
||||||
backgroundColor: this.errorColor
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stepTitleStyle () {
|
|
||||||
var isError = this.tabs[this.activeTabIndex].validationError
|
|
||||||
return {
|
|
||||||
color: isError ? this.errorColor : this.color
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isStepSquare () {
|
|
||||||
return this.shape === 'square'
|
|
||||||
},
|
|
||||||
isTabShape () {
|
|
||||||
return this.shape === 'tab'
|
|
||||||
},
|
|
||||||
fillButtonStyle () {
|
fillButtonStyle () {
|
||||||
return {
|
return {
|
||||||
backgroundColor: this.color,
|
backgroundColor: this.color,
|
||||||
@@ -234,7 +195,6 @@
|
|||||||
this.tabs.splice(index, 0, item)
|
this.tabs.splice(index, 0, item)
|
||||||
// if a step is added before the current one, go to it
|
// if a step is added before the current one, go to it
|
||||||
if (index < this.activeTabIndex + 1) {
|
if (index < this.activeTabIndex + 1) {
|
||||||
console.log('Changing tabs', index, this.activeTabIndex)
|
|
||||||
this.maxStep = index
|
this.maxStep = index
|
||||||
this.changeTab(this.activeTabIndex + 1, index)
|
this.changeTab(this.activeTabIndex + 1, index)
|
||||||
}
|
}
|
||||||
@@ -255,9 +215,6 @@
|
|||||||
tabs.splice(index, 1)
|
tabs.splice(index, 1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isChecked (index) {
|
|
||||||
return index <= this.maxStep
|
|
||||||
},
|
|
||||||
navigateToTab (index) {
|
navigateToTab (index) {
|
||||||
this.$emit('on-change', this.activeTabIndex, index)
|
this.$emit('on-change', this.activeTabIndex, index)
|
||||||
let validate = index > this.activeTabIndex
|
let validate = index > this.activeTabIndex
|
||||||
@@ -363,9 +320,7 @@
|
|||||||
newTab.active = true
|
newTab.active = true
|
||||||
}
|
}
|
||||||
this.activeTabIndex = newIndex
|
this.activeTabIndex = newIndex
|
||||||
this.checkStep()
|
this.activateTabAndCheckStep(this.activeTabIndex)
|
||||||
this.tryChangeRoute(newTab)
|
|
||||||
this.increaseMaxStep()
|
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
tryChangeRoute (tab) {
|
tryChangeRoute (tab) {
|
||||||
@@ -409,13 +364,16 @@
|
|||||||
this.deactivateTabs()
|
this.deactivateTabs()
|
||||||
let tab = this.tabs[index]
|
let tab = this.tabs[index]
|
||||||
tab.active = true
|
tab.active = true
|
||||||
|
tab.checked = true
|
||||||
this.tryChangeRoute(tab)
|
this.tryChangeRoute(tab)
|
||||||
},
|
},
|
||||||
activateTabAndCheckStep (index) {
|
activateTabAndCheckStep (index) {
|
||||||
this.activateTab(index)
|
this.activateTab(index)
|
||||||
this.checkStep()
|
this.checkStep()
|
||||||
this.maxStep = this.startIndex
|
if (index > this.maxStep) {
|
||||||
this.activeTabIndex = this.startIndex
|
this.maxStep = index
|
||||||
|
}
|
||||||
|
this.activeTabIndex = index
|
||||||
},
|
},
|
||||||
initializeTabs () {
|
initializeTabs () {
|
||||||
if (this.tabs.length > 0 && this.startIndex === 0) {
|
if (this.tabs.length > 0 && this.startIndex === 0) {
|
||||||
@@ -440,13 +398,4 @@
|
|||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import "./../assets/wizard";
|
@import "./../assets/wizard";
|
||||||
|
|
||||||
.fade-enter-active, .fade-leave-active {
|
|
||||||
transition: opacity .15s
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */
|
|
||||||
{
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -34,7 +34,19 @@
|
|||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
active: false,
|
active: false,
|
||||||
validationError: null
|
validationError: null,
|
||||||
|
checked: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
shape () {
|
||||||
|
return this.$parent.shape
|
||||||
|
},
|
||||||
|
color () {
|
||||||
|
return this.$parent.color
|
||||||
|
},
|
||||||
|
errorColor () {
|
||||||
|
return this.$parent.errorColor
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<li :class="{active:tab.active}">
|
||||||
|
<a>
|
||||||
|
<div class="wizard-icon-circle"
|
||||||
|
:class="{checked: tab.checked,square_shape:isStepSquare, tab_shape:isTabShape}"
|
||||||
|
:style="[tab.checked ? stepCheckedStyle : {}, tab.validationError ? errorStyle : {}]">
|
||||||
|
|
||||||
|
<transition :name="transition" mode="out-in">
|
||||||
|
<div v-if="tab.active" class="wizard-icon-container"
|
||||||
|
:class="{square_shape:isStepSquare, tab_shape:isTabShape}"
|
||||||
|
:style="[tab.active ? iconActiveStyle: {}, tab.validationError ? errorStyle : {}]">
|
||||||
|
<i v-if="tab.icon" :class="tab.icon" class="wizard-icon"></i>
|
||||||
|
<i v-else class="wizard-icon">{{index + 1}}</i>
|
||||||
|
</div>
|
||||||
|
<i v-if="!tab.active && tab.icon" :class="tab.icon" class="wizard-icon"></i>
|
||||||
|
<i v-if="!tab.active && !tab.icon" class="wizard-icon">{{index + 1}}</i>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<span class="stepTitle"
|
||||||
|
:class="{active:tab.active, has_error:tab.validationError}"
|
||||||
|
:style="tab.active ? stepTitleStyle : {}">
|
||||||
|
{{tab.title}}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
tab: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transition: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
iconActiveStyle () {
|
||||||
|
return {
|
||||||
|
backgroundColor: this.tab.color
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stepCheckedStyle () {
|
||||||
|
return {
|
||||||
|
borderColor: this.tab.color
|
||||||
|
}
|
||||||
|
},
|
||||||
|
errorStyle () {
|
||||||
|
return {
|
||||||
|
borderColor: this.tab.errorColor,
|
||||||
|
backgroundColor: this.tab.errorColor
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stepTitleStyle () {
|
||||||
|
let isError = this.tab.validationError
|
||||||
|
return {
|
||||||
|
color: isError ? this.tab.errorColor : this.tab.color
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isStepSquare () {
|
||||||
|
return this.tab.shape === 'square'
|
||||||
|
},
|
||||||
|
isTabShape () {
|
||||||
|
return this.tab.shape === 'tab'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
+4
-1
@@ -1,11 +1,13 @@
|
|||||||
import FormWizard from './components/FormWizard.vue'
|
import FormWizard from './components/FormWizard.vue'
|
||||||
import TabContent from './components/TabContent.vue'
|
import TabContent from './components/TabContent.vue'
|
||||||
import WizardButton from './components/WizardButton.vue'
|
import WizardButton from './components/WizardButton.vue'
|
||||||
|
import WizardStep from './components/WizardStep.vue'
|
||||||
const VueFormWizard = {
|
const VueFormWizard = {
|
||||||
install (Vue) {
|
install (Vue) {
|
||||||
Vue.component('form-wizard', FormWizard)
|
Vue.component('form-wizard', FormWizard)
|
||||||
Vue.component('tab-content', TabContent)
|
Vue.component('tab-content', TabContent)
|
||||||
Vue.component('wizard-button', WizardButton)
|
Vue.component('wizard-button', WizardButton)
|
||||||
|
Vue.component('wizard-step', WizardStep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Automatic installation if Vue has been added to the global scope.
|
// Automatic installation if Vue has been added to the global scope.
|
||||||
@@ -17,5 +19,6 @@ export default VueFormWizard
|
|||||||
export {
|
export {
|
||||||
FormWizard,
|
FormWizard,
|
||||||
TabContent,
|
TabContent,
|
||||||
WizardButton
|
WizardButton,
|
||||||
|
WizardStep
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user