Make a Modal using Bootstrap CSS and VueJS
The Modal will look and work like a Bootsrap Modal. But instead of using jQuery, VueJS 2.0 is used. The picture below shows the end result.
Make a Vue 2.0 project using the Vue-CLI
This tutorial is using Run-time only. Don’t forget to npm install
the modules and then npm run dev
.
Install Bootstrap 3 CSS
Go and grab it from the Bootstrap CDN. Copy only the the minified CSS. Do not copy the JavaScript. Again, we’ll use VueJS for that.
Open the index.html
file. Place the Minified Bootstrap CSS in the <head>
section.
<DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bootstrap VueJS Modal</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" type="text/css" >
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
Bootstrap 3 CSS is now installed.
Make the Modal Component
Make a Modal.vue
file and save it in the components
folder. It’s inside the src
folder of the project.
Below is the template
for this component. The HTML tags are based from Bootstrap. The CSS classes are exactly the same. But instead of using the Bootstrap fade
CSS class, we use VueJS’ <transition>
component. And since this is a modal, we add name="modal"
attribute to <transition>
. Note that this tag is new in VueJS 2.0.
<template>
<transition name="modal">
<div class="modal" style="display: block">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">
Modal title
</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</transition>
</template>
The outer most <div>
has a style
attribute to override Bootstrap’s .modal
class; this is so the Modal will show up.
And this is it for now! Later on, we’ll add VueJS’s <slot>
tags to make this Modal reusable.
Test the Modal Component
Open this Modal in the App.vue
file. To include the Modal in the App.vue
, we need to import it, register it as a component, and add it in the template.
<script>
// import it
import Modal from './components/Modal';
export default {
// register it as a component
components: {
Modal
}
}
</script>
Below shows the <modal>
component included in the <template>
.
<template>
<div id="wrapper" class="container">
<modal></modal>
</div>
</template>
The modal is now showing on the page:
We need a flag variable to show and hide the Modal.
<script>
export default {
components: {
Modal
},
data() {
return {
showModal: false
}
}
}
</script>
The showModal
flag is default to false
so that the Modal doesn’t show up yet. Let’s make a button that opens the Modal.
<template>
<div id="wrapper" class="container">
<modal v-if="showModal"></modal>
<button type="button" class="btn btn-primary" @click="openModal()">Open Modal</button>
</div>
</template>
The image below shows that the modal is how hidden and a button is added.
If you haven’t noticed, showModal
is on the v-if
of the <modal>
component. So if showModal
is false
, the Modal will not show. If showModal
is true
, then the Modal will show. To open the Modal, we need to set showModal
to true
. To do this, let’s define the openModal()
method.
export default {
components: {
Modal
},
data() {
return {
showModal: false
}
},
methods: {
openModal() {
this.showModal = true;
}
}
}
</script>
Go to the browser and test. Click the button and see the Modal open.
To close the Modal, we need to have a close button. This close button should be in the Modal. As a standard Bootstrap modal, a close button is on the footer.
Making the Modal reusable
VueJS 2.0 has the <slot>
component. We can use it to inject a close button in the Modal component’s footer. Add <slot>
in the Modal.vue
; one in the <header>
, <body>
, and <footer>
.
<template>
<transition name="modal">
<div class="modal" style="display: block">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<slot name="header"></slot>
</div>
<div class="modal-body">
<slot name="body"></slot>
</div>
<div class="modal-footer">
<slot name="footer"></slot>
</div>
</div>
</div>
</div>
</transition>
</template>
Now this Modal can have any header, body and footer content. Each <slot>
has a name for designation.
Define the header and footer content
Modify <modal>
in App.vue
. To make sure we still have the same title as earlier, we’ll use the slot="header"
. Along with it, we define the footer body:
<template>
<div id="wrapper" class="container">
<modal v-if="showModal">
<h3 slot="header" class="modal-title">
Modal title
</h3>
<div slot="footer">
<button type="button" class="btn btn-outline-info" @click="closeModal()"> Close </button>
<button type="button" class="btn btn-primary" data-dismiss="modal" @click="submitAndClose()">
Submit
</button>
</div>
</modal>
. . .
I added a submit button just to elaborate.
Define the closeModal()
This method is defined in the App.vue
‘s method
property because it’s in the scope of App.vue
. It’s not in the scope of Modal.vue
component. This also means that this.showModal
is in the same scope.
<script>
. . .
methods: {
openModal() {
this.showModal = true;
},
closeModal() {
this.showModal = false;
},
submitAndClose() {
. . .
}
}
</script>
Modal mask background
Most modals have a mask behind them so that the user can’t click any other buttons behind the modal. To do this, the entire modal is enclosed by this mask excluding <transition>
. The CSS will be declared in the <style>
section of the Modal.vue
file.
<template>
<transition name="modal">
<div class="modal modal-mask" style="display: block">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<slot name="header"></slot>
</div>
<div class="modal-body">
<slot name="body"></slot>
</div>
<div class="modal-footer">
<slot name="footer"></slot>
</div>
</div>
</div>
</div>
</transition>
</template>
The CSS is defined below
<style>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
display: table;
transition: opacity .3s ease;
}
</style>
That’s it
This is a simple, basic and reusable Modal. The design and layout are exactly like a Bootstrap modal. And, it is a Bootstrap modal! It’s also 100% compatible with VueJS.
Check out the code on GitHub.