rowanwins / vue-dropzone

A Vue.js component for Dropzone.js - a drag’n’drop file uploads utility with image previews
https://rowanwins.github.io/vue-dropzone/docs/dist
MIT License
2.02k stars 1.4k forks source link

Using a fully featured vue component as the preview template #162

Open NikiSchlifke opened 7 years ago

NikiSchlifke commented 7 years ago

Description:

For the purposes of keeping code DRY I'd like to use the html from a existing component as the preview template. Right now, at least according to the documentation I was able to find we are supposed to give the previewTemplate prop a function that returns HTML. I think it would be nicer if it were possible to use a component that was for instance imported from a .vue file.

Steps To Reproduce:

I've tried to import the component and attach it to the data property of the parent that contains the vue2-dropzone component. Passing the data property itself or something akin to

<dropzone :previewTemplate="previewTemplate.render">

does not work, as the render function has not been created when the dropzone component is loaded. It probably shouldn't, but maybe there is a way?

rowanwins commented 7 years ago

Gday @NikiSchlifke

That would be awesome, there's been some related requests (eg here ). I definitely love to do this but I haven't found a way yet. I gather it is complicated downstream but how dropzone.js itself handles the html string that is parsed, when I was digging I found reference to someone from the angular community wanting to do something similar.

Anyway I haven't given up hope yet, Im currently working on an overhaul of this component so Im trying to work it into that.

vrajroham commented 6 years ago

Hi folks,

Version 3 is now released. Check out the new docs for more info.

pscheit commented 6 years ago

@rowanwins you got any progress on this? I tried to have a look at it, but didn't get any angle. I'm not that keen in vue yet, but you got any tips where we can start to solve this issue?

rowanwins commented 6 years ago

Unfortunately not @pscheit - it's a tricky one that I think is dependent on some changes upstream in dropzone itself.

kurbar commented 5 years ago

@rowanwins @pscheit I have found a way to use components as previewTemplates.

The basic gist of it is to delay the initial VueDropzone component creation until you have the raw preview template html.

So this is what I did.

By default, I prevent the vue-dropzone from being loaded:

<vue-dropzone v-if="!loading"...
...
data: () => ({
  loading: true,
  previewHtml: null,

I load my options prop through computed properties but it should work if you load them through data:

computed: {
  options() {
    return {
      url: `${process.env.VUE_APP_API_BASE_URL}/upload`,
      previewTemplate: this.previewHtml,
    };
  },
},

Then I import Vue and my preview template component:

import Vue from 'vue';
import vue2Dropzone from 'vue2-dropzone';
import PreviewTemplate from './upload-media/PreviewTemplate.vue';

The preview component is a simple template with data-dz-* attributes in place where I want them. For example this is my PreviewTemplate component (with Vuetify):

<template>
  <v-card>
    <v-list-item three-line>
      <v-list-item-avatar size="125" tile>
        <div data-dz-thumbnail-bg></div>
      </v-list-item-avatar>
      <v-list-item-content class="align-self-start">
        <v-list-item-title class="headline mb-2"><span data-dz-name></span></v-list-item-title>
        <v-list-item-subtitle><span data-dz-size></span></v-list-item-subtitle>
      </v-list-item-content>
    </v-list-item>
  </v-card>
</template>

<script>
export default {};
</script>

Finally, I mount an instance of the component in my created hook and then pull out its outerHTML, load it into my previewHtml data attribute and end the loading:

created() {
  const ComponentClass = Vue.extend(PreviewTemplate);
  const instance = new ComponentClass();
  instance.$mount();
  this.previewHtml = instance.$el.outerHTML;

  this.loading = false;
}

Now when Dropzone starts initialising, I already have a compiled previewTemplate HTML in my options prop and it works like a charm.

If you want, I can make it into a PR.

AlexanderYW commented 4 years ago

@rowanwins @vrajroham If this is still relevant I've made a way to get "proper" reactive templating for dropzone https://github.com/AlexanderYW/vue-dropzone

And by "proper" i still need to figure out a way to deal with HUGE images without loosing performance (Will look into scaling the images before converting them to base64), but long story short I made it work with slots where it does not loose the @click bindings when being rendered

Feel free to give a hand if you have idea's regarding the performance issues

dkjain commented 4 years ago

Hi AlexanderYW

I made it work with slots where it does not loose the @click bindings when being rendered

This is awesome, actually is exactly what is working on but got stuck as I kept loosing the @click binding inside slot,

Can u pls plz create a demo ASAP on codesandbox or codepen. Already spent almost 2 weeks on this and other related issues, trying to make it work.

Thanks

Alex-Kozynko commented 4 years ago

@rowanwins @vrajroham If this is still relevant I've made a way to get "proper" reactive templating for dropzone https://github.com/AlexanderYW/vue-dropzone

And by "proper" i still need to figure out a way to deal with HUGE images without loosing performance (Will look into scaling the images before converting them to base64), but long story short I made it work with slots where it does not loose the @click bindings when being rendered

Feel free to give a hand if you have idea's regarding the performance issues

Unfortunately this does not work, at first your changed library refused to work at all, I fixed it, but it turned out that it does not support an external container for the template