0

My component vue like this :

<template>
    <div>
        <ul class="list-inline list-photo">
            <li v-for="item in items">
                <div class="thumbnail" v-if="clicked[item]">
                    <img src="https://myshop.co.id/img/no-image.jpg" alt="">
                    <a href="javascript:;" class="thumbnail-check"><span class="fa fa-check-circle"></span></a>
                </div>
                <a v-else href="javascript:;" class="thumbnail thumbnail-upload"
                   title="Add Image" @click="addPhoto(item)">
                    <span class="fa fa-plus fa-2x"></span>
                </a>
            </li>
        </ul>
    </div>
</template>
<script>
    export default {
        props: ['state', 'product'],
        data() {
                return {
                    items: [1, 2, 3, 4, 5],
                    clicked: [] // using an array because your items are numeric
                }
            }
        },
        methods: {
            addPhoto(item) {
                this.$set(this.clicked, item, true)
            }
        }
    }
</script>

If I click a link then it will call method addPhoto

I want if the a link clicked, it will upload image. So it will select the image then upload it and update img with image uploaded.

It looks like the code to upload image will be put in add photo method

I'm still confused to upload image in vue component

How can I solve it?

Success Man
  • 5,513
  • 23
  • 109
  • 205

1 Answers1

1

You can use a component for file picker like this:

<template>
  <input v-show="showNative" type="file" :name="name" @change="onFileChanged" :multiple="multiple" :accept="accept"/>
</template>

<script>

export default {
  props: {
    name: { type: String, required: true },
    show: { type: Boolean, Default: false },
    multiple: { type: Boolean, default: false },
    accept: { type: String, default: "" },
    showNative: { type: Boolean, default: false }
  },
  watch: {
    show(value) {
      if (value) {
        // Resets the file to let <onChange> event to work.
        this.$el.value = "";

        // Opens select file system dialog.
        this.$el.click();

        // Resets the show property (sync technique), in order to let the user to reopen the dialog.
        this.$emit('update:show', false);
      }
    }
  },
  methods: {
    onFileChanged(event) {
      var files = event.target.files || event.dataTransfer.files;
      if (!files.length) {
        return;
      }

      var formData = new FormData();

      // Maps the provided name to files.
      formData.append(this.name, this.multiple ? files : files[0]);

      // Returns formData (which can be sent to the backend) and optional, the selected files (parent component may need some information about files).
      this.$emit("files", formData, files);
    }
  }
}
</script>

And here some information how to use it:

  • import the component -> declare the directive.
  • provide a -> is used for the formData creation (is the name which is going to backend).
  • to display it us the property Note: sync recommended if needed to be opened multiple times in the same page. Check the bottom examples. ( /!\ Vue 2.3 required for sync /!\ )
  • listen to @files event to get an array of selected files as parameter
  • if you want to use it as multiple file select, then provide the property as true.
  • use prop to filter the files (valid accept types: HTML Input="file" Accept Attribute File Type (CSV)).
  • when is set to true, the component displays 'select file' button (input type file), otherwise it is hidden, and windows displayed by Js.

ex: Single select

<file-upload name="fooImport" @files="selectedFile" :show.sync="true" />

ex: Multiple select

<file-upload name="barUpload" @files="selectedFiles" :show.sync="displayUpload" accept="text/plain, .pdf" />
V. Sambor
  • 8,155
  • 4
  • 32
  • 52