DEV Community

Cover image for How to create a reusable modal using VueJS with named slots
Snehal
Snehal

Posted on

How to create a reusable modal using VueJS with named slots

Hello readers…

In today’s blog we are going to see how can we create reusable modal using slot in VueJS.

In most of the case we don’t want to go to new page, do some tasks and redirect back to the main page, in that case we will use the modal which open’s on the same page. This can be used to add, edit, or to show some information. Let us see how can we create a modal with named slots.

First we have to create a component named as Modal.vue in src/components/ directory and add the below code.

<template>
  <transition name="modal-fade">
    <div class="modal-backdrop">
      <div
        class="modal"
        role="dialog"
        aria-labelledby="modalTitle"
        aria-describedby="modalDescription"
      >
        <header class="modal-header" id="modalTitle">
          <slot name="header"> Default Header </slot>
          <button
            type="button"
            class="close-btn"
            @click="close"
            aria-label="Close Modal"
          >
            x
          </button>
        </header>

        <main class="modal-body" id="modalDescription">
          <slot name="body"> Default body content </slot>
        </main>

        <footer class="modal-footer">
          <slot name="footer"> Default Footer! </slot>
          <button
            type="button"
            class="btn-open-modal"
            @click="close"
            aria-label="Close Modal"
          >
            Close Modal
          </button>
        </footer>
      </div>
    </div>
  </transition>
</template>

<script>
export default {
  name: "Modal",
  methods: {
    close() {
      this.$emit("close");
    },
  },
};
</script>
<style>
.modal-backdrop {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: rgba(0, 0, 0, 0.3);
  display: flex;
  justify-content: center;
  align-items: center;
}

.modal {
  background: #FFFFFF;
  box-shadow: 2px 2px 20px 1px;
  overflow-x: auto;
  display: flex;
  flex-direction: column;
  border-radius: 10px;
  width: 80%;
}

.modal-header,
.modal-footer {
  padding: 15px;
  display: flex;
}

.modal-header {
  position: relative;
  border-bottom: 1px solid rgb(227, 231, 233);
  color: blue;
  justify-content: space-between;
}

.modal-footer {
  border-top: 1px solid rgb(227, 231, 233);
  flex-direction: column;
  justify-content: flex-end;
}

.modal-body {
  position: relative;
  padding: 20px 10px;
}

.close-btn {
  position: absolute;
  top: 0;
  right: 0;
  border: none;
  font-size: 20px;
  padding: 10px;
  cursor: pointer;
  font-weight: bold;
  color: red;
  background: transparent;
}

.btn-open-modal {
  color: white;
  background: green;
  border: 1px solid green;
  border-radius: 4px;
  margin: 20px auto;
  padding: 5px;
  width: 40%;
}
.modal-fade-enter,
.modal-fade-leave-to {
  opacity: 0;
}

.modal-fade-enter-active,
.modal-fade-leave-active {
  transition: opacity 0.5s ease;
}
</style>

Enter fullscreen mode Exit fullscreen mode

In the above code, we have created a three slots with their respective name which holds the data according to the name given to it. Like one of the above slots has given a name as a footer when we use this modal in our Main component then the data/content provided by the slot ‘footer’ then its contents is placed in its respective footer slot.

Let’s see it by an example.

Now go to the App.vue file in which we will use the modal we have just created, and add the below code.

<template>
  <div id="app">
    <h3>Example of Reusable Modal using Slot</h3>
    <button type="button" class="btn" @click="openModal()">Open Modal</button>
    <Modal v-show="visible" @close="close">
      <template v-slot:header> Modal
 Header </template>

      <template v-slot:body> You can put your contents within body </template>

      <template v-slot:footer> You can put your footer here </template>
    </Modal>
  </div>
</template>

<script>
import Modal from "./components/Modal";

export default {
  name: "App",
  components: {
    Modal,
  },
  data() {
    return {
      visible: false,
    };
  },
  methods: {
    openModal() {
      this.visible = true;
    },
    close() {
      this.visible = false;
    },
  },
};
</script>

<style>
#app {
  font-family: "Avenir", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.btn {
  background-color: rgb(96, 96, 214);
  color: #fff;
  border-radius: 4px;
  padding: 8px;
  border: none;
  font-weight: bold;
}
</style>
Enter fullscreen mode Exit fullscreen mode

As we see in the above code that in <Modal> we have defined the template with slots and its name. The content/data provided in it will be replaced in the main Modal component.

Now in the same way we can define the modal in any other component as well by providing required contents into it.

If you like the post, subscribe to my blog.

snehalk image

For better understanding you can refer the sandbox.

Thank you for reading. 🦄 ❤️

Discussion (0)