Uploading and previewing multiple files, including images and videos

I am facing an issue with a child component where the input field is obscured by a slotted element. The parent component provides the slotted click event element, along with a preview of the file(s) and the option to delete them. I am struggling to implement the select and preview functionality in the context of a child/parent relationship.

Below is the code I have come up with so far, but I am stuck and confused about the next steps.

The slot successfully triggers the event in the child component, but I encounter a "TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'." error when trying to render the files as currently written. What am I missing here?

If more information is needed, please feel free to ask! Thank you!

NOTE: I also need to ensure compatibility with V-model, but I am unsure how to achieve that at the moment.

UploadMediaFiles (Child Component)

<template>
  <div class="upload-media-files">
    <input
      id="input-file"
      type="file"
      accept="*"
      multiple
      @change="addMedia"
      class="_add-media-input"
      ref="input"
    />
    <label for="input-file">
      <slot :openFileDialog="openFileDialog">
        <img
          src="https://www.clipartmax.com/png/middle/142-1422132_png-file-svg-upload-file-icon-png.png"
          alt=""
        />
      </slot>
    </label>
  </div>
</template>

<style lang="sass" scoped>
input
  display: none
</style>

<script>
export default {
  name: 'UploadMediaFiles',
  props: {
    multiple: { type: Boolean },
    accept: { type: String },
  },
  data() {
    return {
      files: [],
    }
  },
  computed: {},
  methods: {
    async addMedia(event) {
      const files = event.target.files || event.dataTransfer.files
      if (!files.length) return
      console.log(`files → `, files)
      this.files.push(files)
      this.$emit('selected', this.files)
    },

    openFileDialog() {
      this.$refs.input.click()
    },
  },
}
</script>

SelectAndPreviewFiles (Parent Component)

<template>
  <div class="select-and-preview-files">
    <div v-if="selectedFiles">
      <div :key="index" v-for="(selectedFile, index) in selectedFiles">
        <img :src="selectedFile" alt="" />
        <button @click="deleteFile(index)">Delete</button>
      </div>
    </div>
    <UploadMediaFiles @selected="(files) => selectFiles(files)" v-slot="{ openFileDialog }">
      <button @click="openFileDialog">
        <img
          src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Circle-icons-upload.svg/1200px-Circle-icons-upload.svg.png"
          alt=""
        />
      </button>
    </UploadMediaFiles>
  </div>
</template>

<style lang="sass" scoped>
img
  width: 20%
  margin: auto
  display: block
  margin-bottom: 10px
</style>

<script>
import UploadMediaFiles from '../atoms/UploadMediaFiles.vue'
export default {
  name: 'SelectAndPreviewFiles',
  components: {
    UploadMediaFiles,
  },
  props: {},
  data() {
    return {
      selectedFiles: [],
    }
  },
  computed: {},
  methods: {
    selectFiles(files) {
      this.selectedFiles.push(files)
      this.previewImage(files)
    },
    previewImage(files) {
      var vm = this
      for (var index = 0; index < files.length; index++) {
        var reader = new FileReader()
        reader.onload = function (event) {
          const imageUrl = event.target.result
          vm.files.push(imageUrl)
        }
        reader.readAsDataURL(files[index])
      }
    },
    deleteFile(index) {
      this.selectedFiles.splice(index, 1)
    },
  },
}
</script>

CodePen without the parent-child relationship https://codepen.io/LovelyAndy/pen/gOmYGKO?editors=0001

Answer №1

The issue arises from the fact that the input value containing multiple selected files is an array of FileLists, each holding a list of File objects. However, the function previewImage() assumes that the input is an array of File objects.

The problem lies in passing files[index], which is a FileList, as an argument to reader.readAsDataURL(), resulting in an error.

To fix this, it is necessary to iterate through each FileList in the array:

export default {
  methods: {
    selectFiles(files) {
      this.selectedFiles.push(files);
      this.previewImage(files);
    },
    previewImage(files) {
      var vm = this
      for (var index = 0; index < files.length; index++) {
        const fileList = files[index]
        fileList.forEach(file => {
          var reader = new FileReader()
          reader.onload = function (event) {
            const imageUrl = event.target.result
            vm.selectedFiles.push(imageUrl)
          }
          reader.readAsDataURL(file)
        })
      }
    },
  }
}

example

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

eval concealing program in JGraph compared to obfuscation and packing

Many times when the topic of eval is brought up, the response is always the same - avoid using eval. However, I believe there is a valid reason for eval to exist. Nevertheless, there are numerous pitfalls to consider. Regarding jgraph - why do they incorp ...

How to handle blank property values in JavaScript objects and convert them to null in an ASP.NET Web API

Hey there! I'm facing an issue where when I post a JavaScript object to an ASP.NET Web API, some property values are blank like the example below: var o={ ID=1, Fname="Tom", Mname="", Lname="Wilson" } However, in the Web ...

Tips for inserting an element into every tier of a multi-layered array

I am faced with a challenging task of assigning an id field to objects within an array that has infinite levels. The rule is simple - for every level, the ID should correspond to the level number starting from 1. { "name": "Anything2&quo ...

Issue with exporting Three.js to Maya

I've been attempting to utilize the Three.js exporter for Maya found here. However, when I try to load the threeJsFileTranslator.py plug-in from the plug-ins manager in Maya, I encounter an error in the Script Editor: // Error: line 1: invalid synta ...

How to execute a JavaScript function within a Jinja for loop

I am currently working on an HTML page where the variable schedule contains a series of sequential decimal numbers representing seconds. My goal is to develop a function in JavaScript/jQuery that can convert these decimal numbers into time format. However ...

Tips for sending parameters in onClick within a React Functional Component

In my ReactJS Functional Component, I need to pass a few values when a button is clicked. The code snippet for this functionality is below: <span className="edit" onClick={ onClickEdit(value.title, value.details)}> <img src={editImg} height=" ...

Manage the angularJS user interface switch through an external event

I have implemented an AngularJS Material UI switch and I am looking to update its status based on an external event. This event occurs when a MQTT message is received on a specific topic that is published. To achieve this, I am utilizing a Node.js MQTT cli ...

The Vue component is not displaying the image source data as expected

Can anyone provide guidance on how to correctly call an HTML img src link? I have tried various methods but have not been successful. Below is the code snippet from my vue.js app loop: <div class="level-left"> <span class="icon ...

Issue "The only acceptable numeric escape in strict mode is '' for styled elements in Material-UI (MUI)"

Attempting to utilize the numeric quote for quotation marks, I encountered an issue: 'The sole legitimate numeric escape in strict mode is '\0` The snippet of code causing the problem can be seen below: export const Title = styled(Typogra ...

Foreign keys in a one-to-many relationship with Sequelize.js

I am in the process of developing a survey application using Node.js/Express and MySQL incorporating Sequelize.js ORM. However, I am encountering difficulties while establishing the relationship between the two models. My goal is to have the Questions&apo ...

Ways to access the values of checkboxes that are initially checked by default

Recently, I was working on a project that involved multiple checkboxes. My goal was to have the checkboxes pre-checked with values in the form (using reactive form). Users should be able to unselect the boxes as they wish and the data would be stored accor ...

What is the best way to substitute unpredictable dynamic variables on-the-fly?

I am working with a .js file that contains a config structure similar to this: genGetLocations:{ data_url:'restaurants/{var1}/tables/{var2}, } This is just one example. Some configurations may have data_url with more than two dynamic variables. I ...

Replace the facebook plugin using JQuery libraries

Does anyone know how to remove the like button on top of the 'Like box' Facebook plugin using JQuery? I have imported the like box from Facebook and I want to eliminate this like button, but Facebook does not allow me to do so. Therefore, I am t ...

Using Pug language for Vue templates provides an alternative to the traditional "Mustache" syntax

"Mustache" syntax allows for defining data as shown below: <template> <Window> <template v-slot:title > {{title}} </template> </Window> </template> However, when compiled wi ...

Sharing information between pages in React through Router

I am struggling to transfer a single string from one page to another using react router and only functional components. I have created a button that links my pages, but I can't seem to pass the string successfully. Here is an example of the code on th ...

Console Error: Attempting to set the 'className' property of null object results in an

I'm experiencing difficulties setting up the code. The function should display all songs by a specific artist when their name is entered and the button is pressed. JavaScript file: /** * Utilizes AJAX to request data about artists from an online sou ...

Calculate the difference between the current value and the previous value

As I work on developing an app using vue.js, I am currently facing a minor issue. async fetchCovidDataByDay(){ const res = await fetch(`https://api.covid19api.com/live/country/${this.name}/status/confirmed`); const data = await res.json(); this ...

Typescript's Nested Type Assignments

Simply put, I'm making an API call and receiving the following data: { getUserInfo: { country: 'DE', email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3c48594f487c59445d514c5059125f5351">[e ...

js expressive dynamic pattern matching

Hey there! I'm in the process of coding an online store and am currently focusing on implementing the add to cart functionality. My goal is to save product IDs and their quantities in a cookie, which will look something like this: id1:qt1,id2:qt2... I ...

Can you explain the significance of the "@" symbol prefix found in npm package names?

While reading through the Angular Component Router documentation, I came across an npm command that caught my attention: npm install @angular/router --save I'm puzzled by the meaning of @angular/router. Is this entire string a package name? If so, ...