been digging what causes my form wizard not going next after going back to previous step for a day now and found out that it's because of the custom image uploader component.
I use this version https://vee-validate.logaretm.com/v3
EDIT: After further testing, the next button is fired only when I changed the value of the image.
Here's what the code and structure looks like:
SomePage.vue
...
<button v-if="currentStep === 2" @click="currentStep--">Back</button>
<ValidationObserver ref="form" v-slot="{ handleSubmit }">
<form @submit.prevent="handleSubmit(onSubmit)">
<ValidationObserver :key="1" v-if="currentStep === 1">
<ValidationProvider
name="Postcode"
vid="postcode"
rules="required"
v-slot="{ errors }"
>
<label for="postcode">Postcode <small>(required)</small></label>
<input
v-model="account.postcode"
:class="{ 'is-invalid': errors[0] }"
type="text"
class="form-control input-text"
name="postcode"
placeholder="Type in postcode"
>
<span
class="invalid-feedback"
role="alert"
v-if="errors[0]"
>
<strong>{{ errors[0] }}</strong>
</span>
</ValidationProvider>
<!-- Custom uploader component -->
<label for="avatar">Upload your Profile Photo <small>(required)</small></label>
<ImageUpload
field-name="Profile Photo"
is-avatar
button-name="Upload your Photo"
:image="account.avatar"
:aspect-ratio="0"
mine-type="image/png"
@change="account.avatar = $event"
/>
</ValidationObserver>
<ValidationObserver :key="2" v-if="currentStep === 2">
<!-- more fields here -->
<ValidationObserver>
<button type="submit">Submit</button>
</form>
</ValidationObserver>
...
ImageUpload.vue
<template>
<div class="file-upload">
<ValidationProvider
rules="required|image"
ref="provider"
:name="fieldName"
v-slot="{ validate, errors }"
>
<input
ref="file"
type="file"
accept="image/jpeg,image/jpg,image/png"
class="d-none"
@change="onFileChange"
>
<!-- end hidden input -->
<button
v-if="!hasImage"
@click="openFileExplore"
:class="{ 'is-invalid' : errors[0] }"
type="button"
class="file-upload-trigger"
:style="getStyle"
>
<img
class="lazyload"
loading="lazy"
data-src="https://myimagelocation.com/test.png"
alt="Placeholder"
title="Placeholder"
>
<span class="is-button">{{ buttonName }}</span>
</button>
<!-- end button trigger -->
<figure
v-else
class="img"
:style="getStyle"
>
<img
:src="image.urls.original"
alt="One Raise"
>
<figcaption>
<button
@click="onRemove"
class="btn btn-light font-weight-bold"
>
Remove Image
</button>
<!-- end button -->
</figcaption>
<!-- end figcaption -->
</figure>
<!-- end image preview -->
<Crop
v-if="selectedFile"
:blob="selectedFile"
@close="selectedFile = null"
@change="onSuccessTempUpload"
:aspect-ratio="aspectRatio"
:mine-type="mineType"
/>
<!-- end Crop -->
<span
class="invalid-feedback"
role="alert"
v-if="errors[0] || errors"
>
<strong>{{ errors[0] || errors }}</strong>
</span>
</ValidationProvider>
</div>
<!-- end file upload -->
</template>
<script>
import Crop from './Crop'
export default {
name: 'ImageUpload',
$_veeValidate: {
name() {
return this.fieldName
}
},
components: { Crop },
props: {
fieldName: {
type: String,
required: true
},
image: {
type: [Object, null],
default: () => ({})
},
buttonName: {
type: String,
default: 'Upload image'
},
...
},
data: () => ({
selectedFile: null
}),
computed: {
hasImage () {
if (this.image !== null) {
return Object.keys(this.image).length > 0
}
return false
},
},
methods: {
openFileExplore () {
this.$refs.file.value = ''
this.$refs.file.click()
},
async onFileChange (event) {
const { valid } = await this.$refs.provider.validate(event)
if (valid) {
const file = event.target.files[0]
if (typeof file !== 'undefined') {
this.selectedFile = URL.createObjectURL(file)
}
}
},
onRemove () {
this.$emit('change', {})
},
onSuccessTempUpload (event) {
this.selectedFile = null
this.$emit('change', {
key: event.key,
urls: {
original: event.preview
}
})
}
}
}
</script>
[1]: https://vee-validate.logaretm.com/v3
question from:
https://stackoverflow.com/questions/65713188/vee-validate-form-wizard-issue-with-custom-file-uploader-component 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…