Cphml444
Cphml444

Reputation: 89

(Vue and Firebase) I am having issues saving multiple images inside an array

I am trying out an image slider, and instead of inserting the image manually, I want to upload the images to Firestore and store them in an array which will then be returned to the image slider.

I already have a code for uploading images, so I thought I would just reuse it, but instead of having one input field for file upload, I created 3. I thought all I needed to do was to tell the application to save the image url inside an array, but this didn't give any results. It only uploads and stores the first image inside the array, but the two other images do not get uploaded.

What would be the solution to this problem?

Importing the slider images

<form @submit.prevent="handleSubmit">
      <h4>Create new content</h4>
      <input type="text" required placeholder="Insert title" v-model="sliderTitle">
      <label>Choose images for your slider</label>
      <input type="file" @change="handleChange">
      <input type="file" @change="handleChange">
      <input type="file" @change="handleChange">
      <div class="error">{{ fileError }}</div>
      <button v-if="!isPending">Create</button>
      <button v-else disabled>Saving...</button>
   </form>
</template>

<script>

import { ref } from 'vue'
import useStorage from '@/composables/useStorage'
import sliderCollection from '@/composables/sliderCollection'
import { timestamp } from '@/firebase/config'
import { useRouter } from 'vue-router' 

export default {
    setup() {
       const { filePath, url, uploadImage } = useStorage()
       const { error, addDoc } = sliderCollection('slider')
       const sliderTitle = ref('')
       const file = ref(null)
       const fileError = ref(null)
       const isPending = ref(false)
       const router = useRouter();

       const handleSubmit = async () => {
          if (file.value) {
             isPending.value = true
             await uploadImage(file.value)
             await addDoc({
                sliderTitle: sliderTitle.value,
                imageUrl: [url.value],
                filePath: filePath.value,
                createdAt: timestamp()
             })
             isPending.value = false
             if(!error.value) {
                router.push({ name: "Home" })
             }
          }
       }

       // allowed file types

       const types = ['image/png', 'image/jpeg']

       const handleChange = (e) => {
          const selected = e.target.files[0]
          console.log(selected)

          if (selected && types.includes(selected.type)) {
             file.value = selected
             fileError.value = null 
          } else {
             file.value = null
             fileError.value = 'Please select an image of the type JPG or PNG'
          }
       }

       return {
          sliderTitle,
          handleSubmit,
          handleChange,
          fileError,
          file,
          isPending
       }
    }
}
</script>

The slider itself

<template>
  <div v-for="content in slider" :key="content.id">
    <img :src="content.imageUrl" />
  </div>
</template>

    <script>
    const images = [];
    export default {
      props: ['slider'],
      name: "ImageSlider",
      data() {
        return { index: 0, imageUrl: images[0] };
      },
      methods: {
        next() {
          this.index = (this.index + 1) % images.length;
          this.imageUrl = images[this.index];
        },
        autoChangeSlide() {
          setInterval(() => {
            this.next();
          }, 3000);
        },
      },
      beforeMount() {
        this.autoChangeSlide();
      },
    };
    </script>

Upvotes: 3

Views: 115

Answers (1)

Tengju Chi
Tengju Chi

Reputation: 138

If you want to upload multiple images within one request you need to add the multiple keyword in the html like:

<input type="file" @change="handleChange" multiple>

then you need to loop through your files to add multiple images like:

await Promise.all(files.map(async file=>{
if (file.value) {
             isPending.value = true
             await uploadImage(file.value)
             await addDoc({
                sliderTitle: sliderTitle.value,
                imageUrl: [url.value],
                filePath: filePath.value,
                createdAt: timestamp()
             })
             isPending.value = false
             if(!error.value) {
                router.push({ name: "Home" })
             }
          }
}))

I hope this helps it a bit, because your question was a little abstract to see what the real problem is. Could be my language barrier there.

Upvotes: 1

Related Questions