How to build a Reusable Vuejs modal component
Tags: vue, modalvue, vuecomponent
Published: 2019-07-09 08:16:57

---
title: How to build a Reusable Vuejs modal component
published: true
description: Learn on how to build a VueJS modal component and make it reusable on your Vue apps
tags: vuejs,vue,modal vue, vue component
---

![Cover Image](https://jakzaizzat.com/wp-content/uploads/2019/07/Featured-Image.png)


Modal is one of the essential components in the user interface. It's good to display or receive a response from the user without moving to other pages. I'm going to build a Modal component and reusable in every page. 

Modal that we're going to build is a simple modal with static content inside it. 
    
## Create a VueJS component

Create a new file in your Vue apps and define them as Vue components. Set the component name in the script section. 

*Modal.vue*

```vue
    <script>
        export default {
            name: 'Modal'
        };
    </script>
```

I'll be using TailwindCSS to style the components. 

Let me know if you need any tutorial/guide on building UI with TailwindCSS.

*Modal.vue*

```vue
    <template>
      <div class="modal">
        <div class="container">
          <div class="modal__title">Direction</div>
          <p>Get a direction with your favourite apps</p>
          <a href="#" class="btn gmaps">
            <img src="https://img.icons8.com/color/420/google-maps.png"> Google Maps
          </a>
          <a href="#" class="btn waze">
            <img src="https://img.icons8.com/color/420/waze.png"> Waze
          </a>
          <button class="mt-3 border-b border-teal font-semibold">Close</button>
        </div>
      </div>
    </template>
    
    <script>
        export default {
            name: 'Modal'
        };
    </script>
    
    
    <style lang="css" scoped>
        .modal {
          background-color: rgba(0, 0, 0, 0.7);
      }
    </style>
```



## Call the component in your page

For example, I want to call this component on my index page. First of all, import the Vue component first and set into the components object. 

Make sure you're calling the correct path.

*App.vue*

```vue
    <script>
    import ModalDirection from "@/components/common/Modal";
    export default {
      components: {
        ModalDirection
      }
    };
    </script>
```

You've successfully imported a component into the page. You can use the component by using this tag. 

```
<modal-direction></modal-direction>
```

Or 

```
<ModalDirection></ModalDirection>
```


*App.vue*

```vue
<template>
  <div>
    <modal-direction></modal-direction>
  </div>
</template>

<script>
import ModalDirection from "@/components/common/Modal";
export default {
  components: {
    ModalDirection
  }
};
</script>


```

## Add a function to the Modal

One of the features of modal is it's able to be visible or not. It'll be visible when other element triggers a function. How to control the function between component 🤔?


We need to add the new data binding in the App.vue, and we called it **modalOpen** and set it to **false**. We don't want the modal visible when the user enters the page. 

*App.vue*

```vue
    <script>
    import ModalDirection from "@/components/common/Modal";
    export default {
      components: {
        ModalDirection
      },
      data() {
        return {
          modalOpen: false
        };
      }
    };
    </script>
```

Let's create a button to toggle the value of **modalOpen**.

*App.vue*

```vue
<template>
  <div>
    <button class="btn" @click="openModal">Open Modal</button>
    <modal-direction></modal-direction>
  </div>
</template>

<script>
import ModalDirection from "@/components/common/Modal";
export default {
  components: {
    ModalDirection
  },
    data() {
        return {
            modalOpen: false
        }
    },
    methods: {
        openModal() {
            this.modalOpen = !this.modalOpen;
        }    
    }
};
</script>

```

Then,  assigned the **v-model** - modalOpen to the **ModalDirection** component.

```vue
 <modal-direction v-model="modalOpen"></modal-direction>
```

## Receive a data from parent - in component

Now, the data has been passed into the component.  Let’s edit our component to make sure it well received.  We’ll write a prop to accept the data from the  *directModal - model* that we just wrote just now. 

*Modal.vue*

```vue
    <template>
      <div class="modal">
        <div class="container">
          <div class="modal__title">Direction</div>
          <p>Get a direction with your favourite apps</p>
          <a href="#" class="btn gmaps">
            <img src="https://img.icons8.com/color/420/google-maps.png"> Google Maps
          </a>
          <a href="#" class="btn waze">
            <img src="https://img.icons8.com/color/420/waze.png"> Waze
          </a>
          <button class="mt-3 border-b border-teal font-semibold">Close</button>
        </div>
      </div>
    </template>
    
    <script>
        export default {
            name: 'Modal',
            props: {
                value: {
                    required; true
                }
            }
        };
    </script>
    
    
    <style lang="css" scoped>
        .modal {
          background-color: rgba(0, 0, 0, 0.7);
      }
    </style>
```


Cool. Now we’re able to access the data from the parent 🎉.  You can access the data from the *v-model* by using this code.

Template tags 

```vue
    {{ value }}
```

Script Tags

```vue
    {{ this.value }}
```


## Control the modal visibility

We should show the modal if the component receives *true* from the parent. Right now, the modal is full visibility. We should control the visibility of the modal from the *value*. 

Luckily, we have the *v-show* to simplify all of this. Just add the *v-show* tag in the modal tag. 

*Modal.vue*

```vue
    <template>
      <div class="modal" v-show="value">
        <div class="container">
          <div class="modal__title">Direction</div>
          <p>Get a direction with your favourite apps</p>
          <a href="#" class="btn gmaps">
            <img src="https://img.icons8.com/color/420/google-maps.png"> Google Maps
          </a>
          <a href="#" class="btn waze">
            <img src="https://img.icons8.com/color/420/waze.png"> Waze
          </a>
          <button class="mt-3 border-b border-teal font-semibold">Close</button>
        </div>
      </div>
    </template>
```


Modal only visible if the *value* is set to *true*.  

## Send the signal to the parent
Cool, now the modal appears when we clicked the button.  Unluckily, there is one last problem.  How do we close the modal? 

Right now, the parent is controlling the modal from the  *value - v-model*. For now, let’s add *method* to the button close to pass the data to the parent using *custom event.*  

*Modal.vue*

```vue
    <template>
      <div class="modal" v-show="value">
        <div class="container">
          <div class="modal__title">Direction</div>
          <p>Get a direction with your favourite apps</p>
          <a href="#" class="btn gmaps">
            <img src="https://img.icons8.com/color/420/google-maps.png"> Google Maps
          </a>
          <a href="#" class="btn waze">
            <img src="https://img.icons8.com/color/420/waze.png"> Waze
          </a>
          <button @click.prevent="close"
 class="mt-3 border-b border-teal font-semibold">Close</button>
        </div>
      </div>
    </template>
    
    <script>
        export default {
            name: 'Modal',
            props: {
                value: {
                    required: true
                }
            }
              methods: {
                close() {
                  this.$emit("input", !this.value);
                }            
            }
        };
    </script>
    
    
    <style lang="css" scoped>
        .modal {
          background-color: rgba(0, 0, 0, 0.7);
      }
    </style>
```

> 💡 Quick tips: Use .prevent to disabled default action of the event will not be triggered. It can be used for button, form, anchor link, and many more. 

Since, we’re passing the data through *v-model* in the component, by the default the event will be called as an *input* as the event. 

[image:149F520D-B9CC-46C7-8AB7-507F1C172B76-7088-0000631BC02B8581/modal.gif]


Congratulations 🎉

Now, the modal is working. You can turn it on and off by using a component. The best part is reusable. You may use it in a different page without writing the code again. 

## Source Code

*Modal.vue*

```vue
    <template>
      <div class="modal" v-show="value">
        <div class="container">
          <div class="modal__title">Direction</div>
          <p>Get a direction with your favourite apps</p>
          <a href="#" class="btn gmaps">
            <img src="https://img.icons8.com/color/420/google-maps.png"> Google Maps
          </a>
          <a href="#" class="btn waze">
            <img src="https://img.icons8.com/color/420/waze.png"> Waze
          </a>
          <button @click.prevent="close"
 class="mt-3 border-b border-teal font-semibold">Close</button>
        </div>
      </div>
    </template>

    <script>
        export default {
            name: 'Modal',
            props: {
                value: {
                    required: true
                }
            }
              methods: {
                close() {
                  this.$emit("input", !this.value);
                }            
            }
        };
    </script>


    <style lang="css" scoped>
        .modal {
          background-color: rgba(0, 0, 0, 0.7);
      }
    </style>
```


*App.vue*

```vue
<template>
  <div>
    <button class="btn" @click="openModal">Open Modal</button>
    <modal-direction></modal-direction>
  </div>
</template>

<script>
import ModalDirection from "@/components/common/Modal";
export default {
  components: {
    ModalDirection
  },
    data() {
        return {
            modalOpen: false
        }
    },
    methods: {
        openModal() {
            this.modalOpen = !this.modalOpen;
        }    
    }
};
</script>
```

Originally published at [https://jakzaizzat.com](https://jakzaizzat.com/how-to-build-a-reusable-vuejs-modal-component/)