diff --git a/README.md b/README.md
index 42bf93b..bea4c6f 100644
--- a/README.md
+++ b/README.md
@@ -93,6 +93,13 @@ props: {
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`
*/
diff --git a/dev-example/App.vue b/dev-example/App.vue
index c709c72..7e46f3e 100644
--- a/dev-example/App.vue
+++ b/dev-example/App.vue
@@ -1,13 +1,14 @@
+ @on-error="setError"
+ class="card" ref="wizard">
@@ -24,6 +24,9 @@
+
+ {{error}}
+
@@ -34,7 +37,9 @@
name: 'app',
data () {
return {
- loadingWizard: false
+ loadingWizard: false,
+ error: null,
+ count: 0
}
},
methods: {
@@ -44,10 +49,19 @@
setLoading (value) {
this.loadingWizard = value
},
+ setError (error) {
+ this.error = error
+ },
validateAsync () {
+ //simulating an error for the first time and a success for the second time
return new Promise((resolve, reject) => {
setTimeout(() => {
- resolve(true)
+ if (this.count < 1) {
+ this.count ++
+ reject('Some custom error')
+ } else {
+ resolve(true)
+ }
}, 1000)
})
},
diff --git a/src/assets/form-wizard/_wizard-card.scss b/src/assets/form-wizard/_wizard-card.scss
index 5a84124..1df34fc 100644
--- a/src/assets/form-wizard/_wizard-card.scss
+++ b/src/assets/form-wizard/_wizard-card.scss
@@ -1,89 +1,95 @@
-.vue-tab-wizard{
- padding-bottom:20px;
- .icon-circle{
- font-size: 18px;
- border: 3px solid $gray-input-bg;
- border-radius: 50%;
- font-weight: $font-weight-bold;
- width: 70px;
- height: 70px;
- background-color: $white-color;
- position: relative;
- display:flex;
- justify-content: center;
- align-content: center;
- &.square_shape{
- border-radius: 0;
- }
- &.tab_shape{
- width:100%;
- min-width:100px;
- height:40px;
- border:none;
- background-color: $gray-input-bg;
- border-radius:0;
- }
- .icon-container{
- display:flex;
- justify-content: center;
- flex:1;
- border-radius: 40%;
- &.square_shape,&.tab_shape{
- border-radius:0;
- }
- }
- .icon{
- display:flex;
- align-items: center;
- justify-content: center;
- }
+.vue-tab-wizard, .vue-form-wizard {
+ padding-bottom: 20px;
+ .is_error {
+ border-color: $danger-states-color !important;
+ .icon-container {
+ background: $danger-states-color !important;
}
-
- .tab-content{
- min-height: 100px;
- padding: 30px 20px 10px;
+ }
+ .icon-circle {
+ font-size: 18px;
+ border: 3px solid $gray-input-bg;
+ border-radius: 50%;
+ font-weight: $font-weight-bold;
+ width: 70px;
+ height: 70px;
+ background-color: $white-color;
+ position: relative;
+ display: flex;
+ justify-content: center;
+ align-content: center;
+ &.square_shape {
+ border-radius: 0;
}
-
- .card-footer{
- padding: 0 20px;
+ &.tab_shape {
+ width: 100%;
+ min-width: 100px;
+ height: 40px;
+ border: none;
+ background-color: $gray-input-bg;
+ border-radius: 0;
}
-
- .wizard-header{
- padding: 15px 15px 15px 15px;
- position: relative;
- border-radius: 3px 3px 0 0;
- z-index: 3;
- text-align: center;
+ .icon-container {
+ display: flex;
+ justify-content: center;
+ flex: 1;
+ border-radius: 40%;
+ &.square_shape, &.tab_shape {
+ border-radius: 0;
+ }
}
-
- .wizard-title{
- color: $card-black-color;
- font-weight: $font-weight-light;
- margin: 0;
- text-align:center;
+ .icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
+ }
- .category{
- font-size: 14px;
- font-weight: 400;
- color: #9A9A9A;
- margin-bottom: 0px;
- text-align: center;
- }
-
- .wizard-navigation{
- .progress-with-circle{
- position: relative;
- top: 40px;
- z-index: 50;
- height: 4px;
-
- .progress-bar{
- box-shadow: none;
- -webkit-transition: width .3s ease;
- -o-transition: width .3s ease;
- transition: width .3s ease;
- }
- }
+ .tab-content {
+ min-height: 100px;
+ padding: 30px 20px 10px;
+ }
+
+ .card-footer {
+ padding: 0 20px;
+ }
+
+ .wizard-header {
+ padding: 15px 15px 15px 15px;
+ position: relative;
+ border-radius: 3px 3px 0 0;
+ z-index: 3;
+ text-align: center;
+ }
+
+ .wizard-title {
+ color: $card-black-color;
+ font-weight: $font-weight-light;
+ margin: 0;
+ text-align: center;
+ }
+
+ .category {
+ font-size: 14px;
+ font-weight: 400;
+ color: #9A9A9A;
+ margin-bottom: 0px;
+ text-align: center;
+ }
+
+ .wizard-navigation {
+ .progress-with-circle {
+ position: relative;
+ top: 40px;
+ z-index: 50;
+ height: 4px;
+
+ .progress-bar {
+ box-shadow: none;
+ -webkit-transition: width .3s ease;
+ -o-transition: width .3s ease;
+ transition: width .3s ease;
+ }
}
+ }
}
diff --git a/src/components/FormWizard.vue b/src/components/FormWizard.vue
index a8f739c..6d0b00a 100644
--- a/src/components/FormWizard.vue
+++ b/src/components/FormWizard.vue
@@ -14,19 +14,25 @@
-
-
+
+
-
+
{{index + 1}}
{{index + 1}}
+
-
+
{{tab.title}}
@@ -104,6 +110,10 @@
type: String,
default: '#e74c3c'
},
+ errorColor: {
+ type: String,
+ default: '#8b0000'
+ },
shape: {
type: String,
default: 'circle'
@@ -161,9 +171,16 @@
borderColor: this.color
}
},
- stepTitleStyle () {
+ errorStyle () {
return {
- color: this.color
+ borderColor: this.errorColor,
+ backgroundColor: this.errorColor
+ }
+ },
+ stepTitleStyle () {
+ var isError = this.tabs[this.activeTabIndex].validationError
+ return {
+ color: isError ? this.errorColor : this.color
}
},
isStepSquare () {
@@ -207,7 +224,12 @@
this.loading = value
this.$emit('on-loading', value)
},
+ setValidationError (error) {
+ this.tabs[this.activeTabIndex].validationError = error
+ this.$emit('on-error', error)
+ },
validateBeforeChange (promiseFn, callback) {
+ this.setValidationError(null)
// we have a promise
if (promiseFn.then && typeof promiseFn.then === 'function') {
this.setLoading(true)
@@ -215,8 +237,9 @@
this.setLoading(false)
let validationResult = res === true
this.executeBeforeChange(validationResult, callback)
- }).catch(() => {
+ }).catch((error) => {
this.setLoading(false)
+ this.setValidationError(error)
})
// we have a simple function
} else {
@@ -228,6 +251,8 @@
this.$emit('on-validate', validationResult, this.activeTabIndex)
if (validationResult) {
callback()
+ } else {
+ this.tabs[this.activeTabIndex].validationError = 'error'
}
},
beforeTabChange (index, callback) {
@@ -254,6 +279,7 @@
this.activeTabIndex = newIndex
this.checkStep()
this.tryChangeRoute(newTab)
+ this.increaseMaxStep()
return true
},
tryChangeRoute (tab) {
@@ -277,7 +303,6 @@
let cb = () => {
if (this.activeTabIndex < this.tabCount - 1) {
this.changeTab(this.activeTabIndex, this.activeTabIndex + 1)
- this.increaseMaxStep()
} else {
this.isLastStep = true
this.$emit('finished')
diff --git a/src/components/TabContent.vue b/src/components/TabContent.vue
index d306759..31be4ec 100644
--- a/src/components/TabContent.vue
+++ b/src/components/TabContent.vue
@@ -33,7 +33,8 @@
},
data () {
return {
- active: false
+ active: false,
+ validationError: null
}
}
}