2
0
mirror of https://github.com/tenrok/vue-form-wizard.git synced 2026-06-08 17:22:37 +03:00

#29 Extract wizard step into separate component and expose via scoped slot

This commit is contained in:
cristijora
2017-07-31 21:02:31 +03:00
parent f718fe6862
commit 79be005226
7 changed files with 128 additions and 83 deletions
+9 -7
View File
@@ -10,6 +10,15 @@
@on-loading="setLoading"
@on-error="setError"
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">
My first tab
</tab-content>
@@ -20,13 +29,6 @@
<div v-if="error">
{{error}}
</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>
</div>
</template>
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+21 -72
View File
@@ -12,31 +12,18 @@
:style="progressBarStyle"></div>
</div>
<ul class="wizard-nav wizard-nav-pills">
<li v-for="(tab, index) in tabs" :class="{active:tab.active}">
<a href="" @click.prevent="navigateToTab(index)">
<div class="wizard-icon-circle"
:class="{checked:isChecked(index),square_shape:isStepSquare, tab_shape:isTabShape}"
:style="[isChecked(index)? 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>
<slot name="step" v-for="(tab, index) in tabs"
:tab="tab"
:index="index"
:navigate-to-tab="navigateToTab"
:transition="transition">
<wizard-step :tab="tab"
@click.native="navigateToTab(index)"
:transition="transition"
:key="tab.title"
:index="index">
</wizard-step>
</slot>
</ul>
<div class="wizard-tab-content">
<slot>
@@ -89,10 +76,12 @@
</template>
<script>
import WizardButton from './WizardButton.vue'
import WizardStep from './WizardStep.vue'
export default{
name: 'form-wizard',
components: {
WizardButton
WizardButton,
WizardStep
},
props: {
title: {
@@ -181,34 +170,6 @@
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 () {
return {
backgroundColor: this.color,
@@ -234,7 +195,6 @@
this.tabs.splice(index, 0, item)
// if a step is added before the current one, go to it
if (index < this.activeTabIndex + 1) {
console.log('Changing tabs', index, this.activeTabIndex)
this.maxStep = index
this.changeTab(this.activeTabIndex + 1, index)
}
@@ -255,9 +215,6 @@
tabs.splice(index, 1)
}
},
isChecked (index) {
return index <= this.maxStep
},
navigateToTab (index) {
this.$emit('on-change', this.activeTabIndex, index)
let validate = index > this.activeTabIndex
@@ -363,9 +320,7 @@
newTab.active = true
}
this.activeTabIndex = newIndex
this.checkStep()
this.tryChangeRoute(newTab)
this.increaseMaxStep()
this.activateTabAndCheckStep(this.activeTabIndex)
return true
},
tryChangeRoute (tab) {
@@ -409,13 +364,16 @@
this.deactivateTabs()
let tab = this.tabs[index]
tab.active = true
tab.checked = true
this.tryChangeRoute(tab)
},
activateTabAndCheckStep (index) {
this.activateTab(index)
this.checkStep()
this.maxStep = this.startIndex
this.activeTabIndex = this.startIndex
if (index > this.maxStep) {
this.maxStep = index
}
this.activeTabIndex = index
},
initializeTabs () {
if (this.tabs.length > 0 && this.startIndex === 0) {
@@ -440,13 +398,4 @@
</script>
<style lang="scss">
@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>
+13 -1
View File
@@ -34,7 +34,19 @@
data () {
return {
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 () {
+79
View File
@@ -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
View File
@@ -1,11 +1,13 @@
import FormWizard from './components/FormWizard.vue'
import TabContent from './components/TabContent.vue'
import WizardButton from './components/WizardButton.vue'
import WizardStep from './components/WizardStep.vue'
const VueFormWizard = {
install (Vue) {
Vue.component('form-wizard', FormWizard)
Vue.component('tab-content', TabContent)
Vue.component('wizard-button', WizardButton)
Vue.component('wizard-step', WizardStep)
}
}
// Automatic installation if Vue has been added to the global scope.
@@ -17,5 +19,6 @@ export default VueFormWizard
export {
FormWizard,
TabContent,
WizardButton
WizardButton,
WizardStep
}