I am trying to use Dropzone.js within a Rails form that is generated via Vue.js. I've placed the dropzone.js file in app/assets/javascripts/.
I then created a single-file components/dropzone.vue component as such:
export default {
data() {
return {
greeting: 'blah'
}
},
created: function() {
var myDropzone = new Dropzone("div#image-drop", { url: "/file/post"});
}
}
I call this component from my main vue file:
import Vue from 'vue/dist/vue.esm';
import dropzone from 'components/dropzone';
document.addEventListener('DOMContentLoaded', () => {
const listingForm = new Vue({
el: '#listing-multistep',
data: {
activeStep: 0
},
components: { dropzone }
})
})
and in my Rails _form.html.erb partial I have
...
...
...
Images
...
Previous
Next
But Dropzone is not being initialized on
Any idea what I may be doing wrong?
Thanks in advance
解决方案
On first reading this question, I thought you had already created a wrapper component, because it uses . But from the fiddle linked below, that doesn't appear to be the case. When using an external library with Vue, typically you want to wrap the external library functionality in a Vue component. Here is a very basic example.
Vue.component("dropzone",{
template: `
mounted(){
new Dropzone(this.$el, {
url: "/file/post"
})
}
})
Here is a pen demonstrating the component.
Dropzone emits many events, that you may want to customize this basic component to listen to and emit to Vue so that it knows about things that happened.
Original Answer
When the component is created, div#image-drop does not yet exist.
Use mounted.
As mentioned below, since you are hiding parts of the template, you may want to switch to v-show instead of v-if. The difference being that v-show renders the hidden elements to the DOM, but hides them, whereas v-if doesn't render them until they are needed.
If you want to stick with v-if you would need to add a watch to activeStep.
watch:{
activeStep(newVal){
if (3 == newVal)
this.$nextTick(() => new Dropzone("div#image-drop", { url: "/file/post"}))
}
}