One of the most common components in web applications is the modal dialog. Vue modals are rather easy to create and work with, and in this tutorial, we’ll show you how!
Let’s dive right in.
For this tutorial, we will be using the Eclipse IDE with the CodeMix plugin installed.
We can now create our application using the CodeMix Project Wizard. We’ll be using the latest version of all the tech libraries and stacks as at the time of this writing. To create a new Vue Project, navigate to File > New > Project > CodeMix > Vue Project. Ensure you choose the, “A Vue CLI-built application” option in the wizard before clicking Finish.
Once the project is completed, open the integrated Terminal+ for the project using Ctrl/Cmd + Shift + P, and executing the command, “Terminal: Create New Integrated Terminal”. If you have more than one project in your workspace, you will be asked to select your project in the command palette before the Terminal is opened.
In the Terminal, run the following commands to install the required Node modules.
npm install
After the installation is complete, you can serve the application right away, find your application in the Servers view and use the context menu run action to start serving it.
In the components
folder, create a file named AppModal.vue
. You can do this by using the New > Vue file wizard accessible from the project’s context menu. We’ll create a very basic component for now.
Note: For more on CodeMix’s Vue capabilities
<template>
<div>
<div>
<h1>Modal heading</h1>
</div>
<hr>
<div>
<h1>Modal content</h1>
</div>
<hr>
<div>
<button>Close</button>
</div>
</div>
</template>
<script>
export default {
name: 'app-modal',
};
</script>
In App.vue
, we import the AppModal
component like below:
<template>
<div id="app">
<h1>Vue Modal Tutorial</h1>
<app-modal></app-modal>
</div>
</template>
<script>
import AppModal from './components/AppModal';
export default {
components: {
AppModal
}
}
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
</style>
If you’re using a recent version of CodeMix, you’ve probably noticed a new browser pane beside the editor – this pane will update after you save your changes, to show you the current state of the app after your changes have been rebuilt. Your application will now look like this:
Obviously this is no good as the modal is open over our app – we’re going to add a condition under which the modal will show, and a button to display it.
<template>
<div id="app">
<h1>Vue Modal Tutorial</h1>
<app-modal v-if="showModal"></app-modal>
<button @click="openModal" v-if="!showModal">Open Modal</button>
</div>
</template>
<script>
import AppModal from './components/AppModal';
export default {
components: {
AppModal
},
data() {
return {
showModal: false
}
},
methods: {
openModal() {
this.showModal = true;
}
},
}
</script>
Here we created our modal template with two div
tags and one button
element. The button
is used to open our modal. In our second div
tag, we added a v-if=isOpen
directive so that our modal will only display if the isOpen
property is true.
Vue.js slots are handy when we want to embed content inside child components. So let’s allow the App.vue
component to pass DOM elements into the AppModal.vue
component. At the same time, we’ll take the opportunity to add some style to our modal, so replace the contents of AppModal.vue
with the source below.
<template>
<div class="modal" v-if="showModal">
<div v-if="showModal" class="modal-content">
<div class="modal-header">
<slot name="header"></slot>
</div>
<hr>
<div class="modal-body">
<slot name="body"></slot>
</div>
<hr>
<div>
<button>Close</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'app-modal',
props: {
showModal: Boolean
}
};
</script>
<style>
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 600px;
max-width: 100%;
height: 400px;
max-height: 100%;
background: #FFFFFF;
box-shadow: 2px 2px 20px 1px;
overflow-x: auto;
display: flex;
flex-direction: column;
}
</style>
We’ll modify the template section of App.vue
with the template below, to actually pass data to our modal component.
<template>
<div id="app">
<h1>Vue Modal Tutorial</h1>
<button @click="openModal" v-if="!showModal">Open Modal</button>
<app-modal v-if="showModal" :showModal=showModal>
<div slot="header">
<h3 class="modal-title">
CodeMix
</h3>
</div>
<div slot="body">
<p>
With CodeMix, you can join the modern web movement right from your Eclipse IDE!
</p>
</div>
</app-modal>
</div>
</template>
<script>
We need to find a way for passing data from the child component back to the parent, so AppModal component can say, “Hey, App component, can you close this me?”.
We’ll implement a closeModal
method that will use $emit
for this purpose, and we’ll call this from the button, on click.
In AppModal.vue
, add the following to the scripts
section
methods: {
closeModal() {
this.$emit('clicked');
}
},
And we’ll modify our button
to call this method:
<button @click="closeModal">Close</button>
Back in App.vue
we need to receive the clicked event and close the modal, so add the following method to the methods section which already exists:
onChildClick () {
this.showModal = false;
}
And we’ll modify the reference to the app-modal
component to call the above method when receiving a clicked
event:
<app-modal v-if="showModal" :showModal=showModal @clicked="onChildClick">
This is how your app should finally look:
Here are two vue files in their entirety, just in case you missed something.
AppModal.vue
<template>
<div class="modal" v-if="showModal">
<div v-if="showModal" class="modal-content">
<div class="modal-header">
<slot name="header"></slot>
</div>
<hr>
<div class="modal-body">
<slot name="body"></slot>
</div>
<hr>
<div class="modal-footer">
<button @click="closeModal">Close</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'app-modal',
props: {
showModal: Boolean
},
methods: {
closeModal() {
this.$emit('clicked');
}
},
};
</script>
<style>
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 600px;
max-width: 100%;
height: 400px;
max-height: 100%;
background: #FFFFFF;
box-shadow: 2px 2px 20px 1px;
overflow-x: auto;
display: flex;
flex-direction: column;
}
</style>
App.vue
<template>
<div id="app">
<h1>Vue Modal Tutorial</h1>
<button @click="openModal" v-if="!showModal">Open Modal</button>
<app-modal v-if="showModal" :showModal=showModal @clicked="onChildClick">
<div slot="header">
<h3 class="modal-title">
CodeMix
</h3>
</div>
<div slot="body">
<p>
With CodeMix, you can join the modern web movement right from your Eclipse IDE!
</p>
</div>
</app-modal>
</div>
</template>
<script>
import AppModal from './components/AppModal';
export default {
components: {
AppModal
},
data() {
return {
showModal: false
}
},
methods: {
openModal() {
this.showModal = true;
},
onChildClick () {
this.showModal = false;
}
},
}
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
</style>
In this article we’ve learnt how to create a modal dialog with Vue, and explored the use of named slots to distribute content between components.
You can download the source code from our GitHub repository here.
#vue-js #javascript #web-development