Search code examples
javascriptvue.jsvuejs2dropzone

passing index and calling a function through dropzone.js


Everything here is technically working as it should be, but I have one glaring issue: When I add an image to my Dropzone instance, I want it to add the file name of that image to my cards array under imageInfo.

I can't figure out how to call an independent function through Dropzone though.

Specifically, all I need to figure out here is how I can call my imageChange function with file from Dropzone as well as card as it's in the loop.

How can I call that function with both attributes upon added image?

new Vue({
      mixins: [VueClickaway.mixin],
      components: {},
      el: "#commonNameDiv",
      data() {
        return {
          searchString: [''],
          results: [],
          savedAttributes: [],
          cards: [],
          showList: false,
          zoneNumber:[],
          imageZoneNames: [],
          imageInfo: [] 
        }           
      },
      methods: {
        imageChange(file){
            console.log('it worked');
        },
        autoComplete(ev, card) {
          this.results = [];
          console.log(this.searchString);
          if (ev.target.value.length > 2) {
            axios.get('/product/parts/components/search', {
              params: {
                searchString: ev.target.value
              }
            }).then(response => {
              card.results = response.data;
              this.showList = true;
              console.log(this.results);
              console.log(this.searchString);
            });
          }
        },
        saveAttribute(result, card) {
          card.value = result.attribute_value;
          card.results = [];
          card.zone = this.zoneNumber;
          this.showList = false;
        },
        addCard: function() {
            this.cards.push({
              index: "",
              value: "",
              zoneNumber: "",
              results: [],
              componentImage:"",
              imageInfo: ""
            });
            
             // Index of the last card pushed
            let cardIndex = this.cards.length - 1;
            let instance = this; // $vm
            Vue.nextTick(function () {
              new Dropzone("#dropzone-"+cardIndex, {
                maxFilesize: 12,
                renameFile: function (file) {
                    var dt = new Date();
                    var time = dt.getTime();
                    return time + file.name;
                },
                acceptedFiles: ".jpeg,.jpg,.png,.gif",
                addRemoveLinks: true,
                timeout: 50000,
                removedfile: function (file) {
                    console.log(file.upload.filename);
                    var name = file.upload.filename;

                    var fileRef;
                    return (fileRef = file.previewElement) != null ?
                        fileRef.parentNode.removeChild(file.previewElement) : void 0;

                },
                init: function() {
                    this.on("addedfile", 
                    function(file) { 
                        instance.imageZoneNames.push({name: file.upload.filename});
                        console.log(file);
                        console.log(instance.imageZoneNames);

                    });
                }
            });
            });

            console.log('cards here');
            console.log(this.cards);
        },
        hideDropdown() {
          this.showList = false;
        },

      },
      created() {

        let instance = this;

        Dropzone.autoDiscover = false;
      

        this.addCard();

       }
    })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.0/dropzone.js"></script>


<div id="commonNameDiv">
<div class="uk-grid" v-for="(card, i) in cards" :key="i">
                <div class="uk-width-1-10"  >
                    <input v-model=" card.zoneNumber" size="4" type="text" name="mapNumber">
                </div>
                <div class="uk-width-6-10">
                    <input
                      style="width:100%"
                      placeholder="what are you looking for?"
                      v-model="card.value"
                      v-on:keyup="autoComplete($event, card)"
                    >
                    <div v-if="showList" v-on-clickaway="hideDropdown" class="panel-footer componentList" v-if="card.results.length">
                      <ul>
                        <li  v-for="(result, i) in card.results" :key="i">
                          <a v-on:click="saveAttribute(result, card)">@{{ result.attribute_value }}</a>
                        </li>
                      </ul>
                    </div>
                </div>
                <div class="uk-width-3-10">
                    <form v-on:change="imageChange(card)" method="post" action="{{url('product/parts/upload/store')}}" enctype="multipart/form-data"
                          class="dropzone" v-bind:id="'dropzone-'+i" v-model="card.imageInfo">
                    </form>
                </div>
            </div>

            <div style="height: 35px;">
                
            </div>

            <div>
                <a v-on:click="addCard">Add another zone</a>
            </div>>
</div>


Solution

  • The addCard method already has access to the card instance being added to this.cards, so you could pass that card into the callback for the addedfile event. For example, you could add a filename prop to the card instance, and then the addedfile callback could update that prop with info from the file event argument:

    export default {
      methods: {
        addCard() {
          //...
    
          const card = {
            //...
            filename: '',
          }
          this.cards.push(card)
    
          new Dropzone('#dropzone', {
            init() {
              this.on('addedfile', file => {
                card.filename = file.upload.filename
              })
            }
          })
        }
      }
    }
    

    codepen