Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Inject the right set of Props into Modal based on clicked button ID

I am facing a problem, which I am sure is simple to solve, however, I cannot figure out the solution to it.
The problem is the following:

I am writing a Vue.js application. I have a component with 3 buttons in it. Each button is meant to trigger a Modal component, and inject the right header and body into the Modal for the user to read. I can hard code a single header and body into the Modal no problem, however, I am having difficulties how to connect the right buttons with the right set of Props being injected into the Modal.

My code is the following:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Component with a set of buttons in it which are meant to trigger the Modal component:

<template>
  <div class="container">
    <div class="wrapper-child-info">
      <div class="info-wrapper">
        <button class="myButton" @click="showModal">Button1</button>
        <br />
        <button class="myButton" @click="showModal">Button2</button>
        <br />
        <button class="myButton" @click="showModal">Button3</button>
//Hard coding the title and bodyMessage triggers the Modal well -> Done for testing purposes -  needs to be eddited; so the Modal title and body change when different buttons are clicked
        <Modal  title='This is my Modal title' bodyMessage='This is my Modal body message' v-show="isModalVisible" @close="closeModal"/>
      </div>
    </div>
    <div class="wrapper-child-gallery">
      <div class="gallery-wrapper">
          <SimpleGallery galleryID="my-test-gallery" :images="images" />
      </div>
    </div>
  </div>
</template>

<script>

import SimpleGallery from '../components/PhotoGallery.vue';
import Modal from '../components/Modal.vue';

export default {
  name: 'homePage',
  components: {
    SimpleGallery,
    Modal
  },

  data() {
    return {
      images: [],
      isModalVisible: false,
      modalMessages: [
        { id: 1, title: 'This is my First Modal title', bodyMessage: 'This is my first Modal message' },
        { id: 2, title: 'This is my Second Modal title', bodyMessage: 'This is my second Modal message' },
        { id: 3, title: 'This is my Third Modal title', bodyMessage: 'This is my third Modal message' },
      ]
    };
  },

  mounted() {
    this.importAll(require.context('@/assets/images/', true, /\.png$/));
  },

  methods: {
    importAll(r) {
      r.keys().forEach(key => (this.images.push({ largeURL: r(key), thumbnailURL: r(key) })));
    },
    showModal() {
        this.isModalVisible = true;
      },
      closeModal() {
        this.isModalVisible = false;
      }
  },
};
</script>

My Modal component:

<template>
<transition name="modal-fade">
  <div class="modal-backdrop">
    <div class="modal">
      <header class="modal-header">
        <slot name="header">
          {{ title }}
        </slot>
        <button
          type="button"
          class="btn-close"
          @click="close"
        >
          x
        </button>
      </header>

      <section class="modal-body">
        <slot name="body">
          {{ bodyMessage }}
        </slot>
       </section>
    </div>
  </div>
</transition>
</template>

<script>
  export default {
    name: 'Modal',
    methods: {
      close() {
        this.$emit('close');
      },
    },
    props: ['title', 'bodyMessage']
  };
</script>

Could anyone point me how to inject the right modalMessages to the Modal when the right button is clicked (e.g Button1 injects modalMessage with ID 1 etc)? I have tried a few solutions and none of them seem to work.
I would be very grateful for any help!
Thank you kindly!

>Solution :

You can set and pass index of modalMessages in showModal method, and bind props in modal component:

Vue.component('modal', {
  template: `
  <transition name="modal-fade">
    <div class="modal-backdrop">
      <div class="modal">
        <header class="modal-header">
          <slot name="header">{{ title }}</slot>
          <button type="button" class="btn-close"  @click="close">x</button>
        </header>
        <section class="modal-body">
          <slot name="body">{{ bodyMessage }}</slot>
         </section>
      </div>
    </div>
  </transition>
  `,
  methods: {
    close() {
      this.$emit('close');
    },
  },
  props: ['title', 'bodyMessage']
})

new Vue({
  el: '#demo',
  data() {
    return {
      isModalVisible: false,
      selected: null,
      modalMessages: [{ id: 1, title: 'This is my First Modal title', bodyMessage: 'This is my first Modal message' }, { id: 2, title: 'This is my Second Modal title', bodyMessage: 'This is my second Modal message' }, { id: 3, title: 'This is my Third Modal title', bodyMessage: 'This is my third Modal message' },]
    };
  },
  methods: {
    showModal(id) {
      this.selected = this.modalMessages.find(m => m.id === id)
      this.isModalVisible = true;
    },
    closeModal() {
      this.isModalVisible = false;
    }
  },
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
  <div class="container">
    <div class="wrapper-child-info">
      <div class="info-wrapper">
        <div v-for="(msg, i) in modalMessages" :key="i">
          <button class="myButton" @click="showModal(msg.id)">Button {{ msg.id }}</button>
        </div>
        <Modal :title='selected?.title' :body-message='selected?.bodyMessage' v-show="isModalVisible" @close="closeModal"/>
      </div>
    </div>
  </div>
</div>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading