Search code examples
vue.jsmodal-dialogpopupv-for

(Vue.js) I want to make image 1 pop up when I click on image 1, and I want image 2 to pop up when I click on image 2


There are several images. I want to make image 1 pop up when I click on image 1, and I want image 2 to pop up when I click on image 2. Can I solve it using the index in class?

Carousel.vue

<template>
  <div v-for="(item, index) in items" :key="index">
    <img :src="item.thumbnail" />
    <button type="button" @click="imgClick()" :class="`img-index--${index}`">button-{{ index }}</button>
  </div>
  <Modal v-if="showModal" @close="showModal = false">
    <div slot="body" v-for="(item, index) in items" :key="index">
      <img :src="item.thumbnail" :class="`img-index--${index}`"/>
    </div>
  </Modal>
</template>

<script>
import Modal from './Modal.vue'
export default {
  props: {
    items: { type: Array, default: () => [] }
  },
  data() {
    return {
      showModal: false
    }
  },
  methods: {
    imgClick() {
      this.showModal = !this.showModal;
    }
  },
  components: {
    Modal: Modal
  }
}
</script>

Solution

  • You can build a new data from your items prop and inject a new property show: false for each image.

    You don't need 2 v-for loops this way. You can put the Modal component inside the first loop and just use the item.show to display or not the modal.

    <template>
      <div>
        <div v-for="(item, index) in photos" :key="index">
          <div @click="imgClick(item)" style="cursor:pointer;>
            <img :src="item.thumbnail" />
          </div>
          <Modal v-if='item.show' @close="item.show = false">
            <div slot='body'>
              <img :src="item.thumbnail" :class="`img-index--${index}`"/>
            </div>        
          </Modal>
        </div>
      </div>
    </template>
    
    <script>
    import Modal from './Modal.vue'
    export default {
      props: {
        items: { type: Array, default: () => [] }
      },
      data() {
        return {
          photos: {}
        }
      },
      created() {
        this.photos = this.items.map(item => {
          return { ...item, show: false }
        })
      },
      methods: {
        imgClick(item) {
          item.show = true
        }
      },
      components: {
        Modal: Modal
      }
    }
    </script>
    

    Fiddle example here


    Note: you can wrap the thumbnail inside a div to manage the click image.