A
A
Alex2019-08-14 09:57:42
Vue.js
Alex, 2019-08-14 09:57:42

How to create a set of blocks for loading images on vue?

It is necessary to create fields for loading images with preview loading on vuejs. Earlier in this project, a component was created for loading one image and without the function of removing this image from the field. Now it has become necessary to create a set of blocks appearing one after another when loading an image into the previous block. And additionally, deleting the image if it was uploaded is not what you need. The entire source code is presented below, shortened, leaving only the necessary. I tried to implement it myself but ran into problems.
1) if the variable in which the images will be stored is an array, then when deleting the elements are shifted and a jamb occurs with the display of new ones
2) the jamb is also observed periodically with the removal of the block
Those. now everything works in the direction of loading images, but there is no
fiddle to demonstrate the work in the opposite direction

Code for clarity and suddenly if the fidl is lost

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <set-imgs
    :name="'instagram-gig-'" 
    :images="images"
    :max-amount="3"
    :count-per-row="3"/>
</div>

Vue.component('input-img', {
  template: `
    <div class="card-input-img" :style="{'padding-top': height}">
      <i 
        class="card-input-img__icon material-icons card-input-img__size_sm"
        :class="{'card-input-img__icon_remove': (hasRemove && img.src)}" 
        v-text="(hasRemove && img.src) ? 'x' : '+'" 
        @click="removeImg"/>
      <img 
        v-if="img.src || background" :src="img.src || background" 
        class="card-input-img__image card-input-img__image_size_cover">
      <input 
        type="file" 
        :name="name"
        accept="image/*"
        @change="fileChangeHandler">
    </div>`,
  props: {
    name: {
      type: String,
      required: true
    },
    height: {
      type: String,
      default: '100%'
    },
    img: {
      type: Object,
      default: null
    },
    background: {
      type: String
    },
    hasRemove: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      newImg: {
        file: null,
        src: null
      },
      firstUpload: true,
    }
  },
  created() {
    this.newImg = this.img
  },
  methods: {
    fileChangeHandler(e) {
      this.newImg.file = e.target.files[0];
      if( this.newImg.file ) {
        let reader = new FileReader();
        reader.onloadend = () => {
          const image  = new Image();
          image.onload = () => {

            this.newImg.src = image.src;

            this.$emit('update:img', this.newImg);
            if(this.firstUpload) {
              this.$emit('first-uploaded', this.newImg);
              this.firstUpload = false;
            }
          }
          image.src = reader.result;
        }
        reader.readAsDataURL(this.newImg.file);
      } 
    },
    removeImg() {
      document.querySelector(`[type="file"][name="${this.name}"]`).value = null;
      this.$emit('remove');
      this.newImg = {
        file: null,
        src: null
      };
      this.firstUpload = true;
    }
  }
});

Vue.component('set-imgs', {
  template: `
    <div class="grid grid_col_3 grid_gap_s">
      <input-img 
        v-for="(image, i) in images"
        :key="i"
        :name="name + i" 
        :background="image.src"
        :img.sync="image" 
        @update:img="image = $event"
        @first-uploaded="addFieldNextImage"
        @remove="removeElem(i)" />
    </div>`,
  props: {
    name: {
      type: String,
      required: true
    },
    img: Object,
    maxAmount: {
      type: Number,
      default: 3,
    },
    countPerRow: {
      type: Number,
      default: 3,
    },
    images: {
      type: Array,
      default: () =>  [{file: null, src: null}]
    }
  },
  methods: {
    addFieldNextImage() {
      if(this.images.length < this.maxAmount) { 
        this.images.push({ file: null, src: null });
      }
    },
    removeElem(i) {
      this.images.splice(i, 1);
    },
  }
});

new Vue({
  el: '#app',
  data() {
    return {
      images: [{file: null, src: null}],
    }
  },
});

Answer the question

In order to leave comments, you need to log in

1 answer(s)
0
0xD34F, 2019-08-14
@pilolin

https://jsfiddle.net/j37rL89k/

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question