go to part...
Before we get started make sure your Laravel project has something like "vue": "^2.1.10"
in the devDependencies
section of your package.json
file (you might have a different version than 2.1.10). After that run npm run install
in your terminal inside the root folder of your project if you haven't done this yet.
The View
To start let's place our future Vue component into a view. Open your main layout file (resources/views/layouts/app.blade.php
or whatever you have) and add a new element somewhere at the top of the <div id="app">
. We'll call our component notification
.
<notification></notification>
We're going to expand this as we need to check if anything was flashed from a controller. We'll pass the flashed message and its type to the component via properties. status
is what flashed by Laravel's authentication system, but I wanted to flash my messages under a different session key, hence the double condition. As for the type
we'll simply be passing a bootstrap alert class.
@if (session('notification'))
<notification type="{{ session('notificationType') }}" message="{{ session('notification') }}"></notification>
@elseif (session('status'))
<notification type="alert-primary" message="{{ session('status') }}"></notification>
@else
<notification></notification>
@endif
The Component
Now let's create the Vue component file in the resources/assets/js/components
folder. We'll call it Notification.vue
. Then register the component as a global component in the resources/assets/js/app.js
file.
Vue.component('notification', require('./components/Notification.vue'));
Open the component file and add this boilerplate code:
<template>
</template>
<style>
</style>
<script>
export default {
}
</script>
Now we can start building it up. Every Vue template must have a single parent element. We'll also use that element for positioning of our notification. The div inside is the actual notification element.
<template>
<div class="notification-wrapper">
<div class="notification alert alert-primary">
Some random notification
</div>
</div>
</template>
At his point you can run npm run dev
in your terminal to compile the component. Then go to any page of your website and make sure you see the text Some random notification
at the top of the page. Now let's apply some css. Edit the <style>
block like this:
<style>
.notification-wrapper {
position: fixed;
left: 50%;
top: 2rem;
z-index: 10000;
}
.notification {
position: relative;
left: -50%;
}
</style>
This will put our notification at the top of the screen centering it horizontally. I set a random big number for the z-index
so that it always shows on top of everything else.
Let's move on to the functionality. We're passing two properties to our component. Let's accept them. We're going to work within the <script>
block now.
<script>
export default {
props: ['type', 'message']
}
</script>
Below the props
we're going to form the data object. Don't forget to add a comma after the props
array.
data() {
return {
show: false,
notification: this.message,
alertClass: this.type,
hideTimeout: false
}
}
The show
property will control the visibility of the notification. By default it will be hidden. hideTimeout
will be used for hiding the notification after a few seconds.
Now let's go back to our template and bind the data. This is what the template should look like now:
<div class="notification-wrapper">
<div :class="'notification alert ' + alertClass"
v-show="show"
v-text="notification"></div>
</div>
The "v-show" attribute controls an element's visibility and displays it only when the variable bound to it returns true.
Now we need to display the notification after the component has been created if any default data has been passed to it (if a message has been flashed by a controller). Add this to our script:
created () {
if (this.notification) {
this.showNotification();
}
},
methods: {
showNotification() {
this.show = true;
}
}
In order to display the notification we just need to set this.show
to true
. I'd also like to automatically hide the notification, say, after 5 seconds. In order to do this we just need to set a timeout which will set this.show
to false
after 5 seconds. Make these changes to the methods:
showNotification() {
this.show = true;
this.hideNotification();
},
hideNotification() {
this.hideTimeout = setTimeout(() => {
this.show = false;
}, 5000);
}
We're saving the timeout in a variable for a reason. Sometimes you don't want to wait for the whole 5 seconds and want to close the notification right away. We're going to add another method for that right after the hideNotification()
method.
destroyNotification() {
this.show = false;
clearTimeout(this.hideTimeout);
}
We need to clear the timeout so that if another notification is being showed shortly after the last one, the new one stays visible for the full 5 seconds. Now we just need to bind this function to the click event of our notifications. Modify the template like this:
<div :class="'notification alert ' + alertClass"
v-show="show"
v-text="notification"
@click="destroyNotification"></div>
We're done with the main part of development. If you want to flash a message from a controller just attach this to your response:
->with('notification', 'Data has been saved successfully!') // The message
->with('notificationType', 'alert-success'); // A Bootstrap alert class
Notifications From JavaScript
Finally, you'd probably want to display these notifications dynamically by calling a JavaScript method. To achieve this you should do the following. Open resources/assets/js/bootstrap.js
and at the very bottom add:
window.Vue = require('vue');
window.events = new Vue();
window.showNotification = function(message, type = 'alert-primary') {
window.events.$emit('showNotification', message, type);
}
Here we've created a global JS function that emits a global Vue event. We pass a message and a notification type with this event. Type equals to alert-primary
by default, so we don't have to pass it every the time.
We'll listen for this event inside our component. Set a listener within the created()
method:
window.events.$on('showNotification', (message, type) => {
this.notification = message;
this.alertClass = type;
this.showNotification();
});
Now you can call this method from anywhere in your JavaScript whenever you want to show a notification.
showNotification('Oops! Something went wrong...', 'alert-danger');
Complete Code
resource/views/layouts/app.blade.php
(or whatever is your main layout file)
...
<body>
<div id="app">
@if (session('notification'))
<notification type="{{ session('notificationType') }}" message="{{ session('notification') }}"></notification>
@elseif (session('status'))
<notification type="alert-primary" message="{{ session('status') }}"></notification>
@else
<notification></notification>
@endif
...
</div>
</body>
...
resources/assets/js/app.js
require('./bootstrap');
window.Vue = require('vue');
Vue.component('notification', require('./components/Notification.vue'));
const app = new Vue({
el: '#app'
});
resources/assets/js/bootstrap.js
window.Vue = require('vue');
window.events = new Vue();
window.showNotification = function(message, type = 'alert-primary') {
window.events.$emit('showNotification', message, type);
}
resources/assets/js/components/Notification.vue
<template>
<div class="notification-wrapper">
<div :class="'notification alert ' + alertClass"
v-show="show"
v-text="notification"
@click="destroyNotification"></div>
</div>
</template>
<style>
.notification-wrapper {
position: fixed;
left: 50%;
top: 2rem;
z-index: 10000;
}
.notification {
position: relative;
left: -50%;
}
</style>
<script>
export default {
props: ['type', 'message'],
data() {
return {
show: false,
notification: this.message,
alertClass: this.type,
hideTimeout: false
}
},
created () {
if (this.notification) {
this.showNotification();
}
window.events.$on('showNotification', (message, type) => {
this.notification = message;
this.alertClass = type;
this.showNotification();
});
},
methods: {
showNotification() {
this.show = true;
this.hideNotification();
},
hideNotification() {
this.hideTimeout = setTimeout(() => {
this.show = false;
}, 5000);
},
destroyNotification() {
this.show = false;
clearTimeout(this.hideTimeout);
}
}
}
</script>
All the materials at voerro are absolutely free and are worked on in the author's spare time. If you found any of the tutorials helpful, please consider supporting the project. Thank you!