Appearance
SweetAlert2
- SweetAlert2 is a popular JavaScript library that provides:
- Toast messages e.g. when a record is successfully deleted from or updated in the database
- Popup confirmation dialog box e.g. when deleting a record from the database
- To use SweetAlert2 in a Laravel project, you need to install the npm package (as a dev dependency) and create a JavaScript file that imports the SweetAlert2 library
Install SweetAlert2
- Start by installing SweetAlert2 with the terminal command:
npm install sweetalert2 --save-dev
Preparation
- Create a JavaScript file sweetAlert2.js in the
resources/js
folder - Open the resources/js/app.js file and add import sweetAlert2.js at the end of the file
js
import './bootstrap';
...
import './sweetAlert2';
...
import './bootstrap';
...
import './sweetAlert2';
...
1
2
3
4
2
3
4
- Open the JavaScript file resources/js/sweetAlert2.js
- Import the SweetAlert2 library
- Add the SweetAlert2 library (
Swal
) to the window object
js
import Swal from 'sweetalert2';
window.Swal = Swal;
import Swal from 'sweetalert2';
window.Swal = Swal;
1
2
2
- Now you can use SweetAlert2 on every page of your application
- The disadvantage of this approach is that you have to write the full Swal 'fire' method every time you want to use SweetAlert2
- To avoid this, you can create a default configuration for a toast message and for a popup confirmation dialog box and overwrite the default configuration when needed
- This keeps the code DRY (Don't Repeat Yourself) and makes our code in the components and Blade files more readable and a lot shorter
Toast message
- Add the following code to the sweetalert2.js file:
- This code creates a default toast message with the SweetAlert2 library
- Line 5: this function is called whenever an event with the name
swal:toast
is triggered - Line 7 - 18:
Swal.mixin()
contains the default configuration for our toast message - Line 20: calls the
convertAttributes()
function to convert some attributes of the event- The property
background
can contain, by default, any CSS color value (e.g.#ff0000
,red
,rgb(255, 0, 0)
,rgba(255, 0, 0, 0.5)
, ...) - But now we can also use some predefined names for the background color:
danger
,error
,warning
,primary
;info
andsuccess
(the wordsdanger
anderror
are converted to'rgb(254, 226, 226)'
etc.) - If the property
text
is set, the property will be transformed to the propertyhtml
and then removed
- The property
- Line 22: calls the
Toast.fire()
method and pass the configuration properties to show the actual toast message
- Line 5: this function is called whenever an event with the name
js
import Swal from "sweetalert2";
window.Swal = Swal;
// toast with default settings and event listener
window.addEventListener('swal:toast', event => {
// default settings for toasts
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
background: 'white',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
}
});
// convert some attributes
let config = Array.isArray(event.detail) ? event.detail[0] : event.detail;
config = convertAttributes(config);
// override default settings or add new settings
Toast.fire(config);
});
function convertAttributes(attributes) {
// convert predefined 'words' to a real color
switch (attributes.background) {
case 'danger':
case 'error':
attributes.background = 'rgb(254, 226, 226)';
break;
case 'warning':
attributes.background = 'rgb(255, 237, 213)';
break;
case 'primary':
case 'info':
attributes.background = 'rgb(207, 250, 254)';
break;
case 'success':
attributes.background = 'rgb(220, 252, 231)';
break;
}
// if the attribute 'text' is set, convert it to the attribute 'html'
if (attributes.text) {
attributes.html = attributes.text;
delete attributes.text;
}
return attributes;
}
import Swal from "sweetalert2";
window.Swal = Swal;
// toast with default settings and event listener
window.addEventListener('swal:toast', event => {
// default settings for toasts
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
background: 'white',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
}
});
// convert some attributes
let config = Array.isArray(event.detail) ? event.detail[0] : event.detail;
config = convertAttributes(config);
// override default settings or add new settings
Toast.fire(config);
});
function convertAttributes(attributes) {
// convert predefined 'words' to a real color
switch (attributes.background) {
case 'danger':
case 'error':
attributes.background = 'rgb(254, 226, 226)';
break;
case 'warning':
attributes.background = 'rgb(255, 237, 213)';
break;
case 'primary':
case 'info':
attributes.background = 'rgb(207, 250, 254)';
break;
case 'success':
attributes.background = 'rgb(220, 252, 231)';
break;
}
// if the attribute 'text' is set, convert it to the attribute 'html'
if (attributes.text) {
attributes.html = attributes.text;
delete attributes.text;
}
return attributes;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
TIP
- All possible options for the toast message can be found on the SweetAlert2 website
- You need at least the
title
or thetext
/html
properties configured, otherwise the toast will be empty
- Some examples of how to use the toast message:
js
document.getElementById('btnToast').addEventListener('click', () => {
window.dispatchEvent(new CustomEvent('swal:toast', {
detail: {
title:'Hello world',
text: 'Message from vanilla js',
icon: 'success',
background: 'success',
}
}));
});
document.getElementById('btnToast').addEventListener('click', () => {
window.dispatchEvent(new CustomEvent('swal:toast', {
detail: {
title:'Hello world',
text: 'Message from vanilla js',
icon: 'success',
background: 'success',
}
}));
});
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Popup confirmation dialog box
- Add the following code to the sweetalert2.js file:
- This code creates a default popup confirmation dialog box with the SweetAlert2 library
- Line 8: this function is called whenever an event with the name
swal:confirm
is triggered - Line 10 - 23:
Swal.mixin()
contains the default configuration for the confirmation dialog box - Line 26 - 27: move the
next
property to thenextEvent
variable and delete it from theevent.detail
object - Line 29: cals the
convertAttributes()
function to convert some attributes of the event (see above) - Line 31: calls the
fire()
method and pass the configuration properties to show the actual confirmation dialog box - Line 32 - 38: the
fire()
method returns a promise- Line 34: if the promise is resolved, check if the value of
isConfirmed
is set totrue
(you clicked on the conform button ) and if the variableNextEvent
is set - If both conditions are true:
- Line 36: dispatch a Livewire event with
event
as the event name andparams
as the payload
- Line 36: dispatch a Livewire event with
- Line 34: if the promise is resolved, check if the value of
- Line 8: this function is called whenever an event with the name
js
import Swal from "sweetalert2";
window.Swal = Swal;
// toast with default settings and event listener
window.addEventListener('swal:toast', event => { ... });
// confirm modal with default settings and event listener
window.addEventListener('swal:confirm', event => {
// default settings for confirm modals
const Confirm = Swal.mixin({
width: 600,
position: 'center',
backdrop: true,
showCancelButton: true,
cancelButtonText: 'Cancel',
cancelButtonColor: 'silver',
showConfirmButton: true,
confirmButtonText: 'Yes',
confirmButtonColor: 'rgb(31, 41, 55)',
reverseButtons: true,
allowEscapeKey: true,
allowOutsideClick: true,
});
// move the 'next' property to the 'nextEvent' variable and delete it from the 'event.detail' object
let config = Array.isArray(event.detail) ? event.detail[0] : event.detail;
const NextEvent = config.next ;
delete config.next;
// convert some attributes
config = convertAttributes(config);
// override default settings or add new settings
Confirm.fire(config)
.then(result => {
// execute this function if the confirm button is clicked AND if a 'NextEvent' is not empty
if (result.isConfirmed && NextEvent) {
// dispatch a Livewire event with 'event' as the event name and 'params' as the payload
window.Livewire.dispatch(NextEvent.event, NextEvent.params);
}
});
});
function convertAttributes(attributes) { ...}
import Swal from "sweetalert2";
window.Swal = Swal;
// toast with default settings and event listener
window.addEventListener('swal:toast', event => { ... });
// confirm modal with default settings and event listener
window.addEventListener('swal:confirm', event => {
// default settings for confirm modals
const Confirm = Swal.mixin({
width: 600,
position: 'center',
backdrop: true,
showCancelButton: true,
cancelButtonText: 'Cancel',
cancelButtonColor: 'silver',
showConfirmButton: true,
confirmButtonText: 'Yes',
confirmButtonColor: 'rgb(31, 41, 55)',
reverseButtons: true,
allowEscapeKey: true,
allowOutsideClick: true,
});
// move the 'next' property to the 'nextEvent' variable and delete it from the 'event.detail' object
let config = Array.isArray(event.detail) ? event.detail[0] : event.detail;
const NextEvent = config.next ;
delete config.next;
// convert some attributes
config = convertAttributes(config);
// override default settings or add new settings
Confirm.fire(config)
.then(result => {
// execute this function if the confirm button is clicked AND if a 'NextEvent' is not empty
if (result.isConfirmed && NextEvent) {
// dispatch a Livewire event with 'event' as the event name and 'params' as the payload
window.Livewire.dispatch(NextEvent.event, NextEvent.params);
}
});
});
function convertAttributes(attributes) { ...}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
- An example of how to use the popup confirmation dialog box:
(This example is a simplified version of how we delete a genre in this project)
- When you click on the delete (trash) button, the confirmation dialog box is shown
- The property
next
contains the event name (event
) and the payload (params
) that will be dispatched when the confirm button is clicked - If the cancel button is clicked, the confirmation dialog box is closed and nothing happens
php
@click="$dispatch('swal:confirm', {
html: 'Delete {{ $genre->name }}?',
cancelButtonText: 'NO!',
confirmButtonText: 'YES DELETE THIS GENRE',
next: {
event: 'delete-genre',
params: {
id: {{ $genre->id }}
}
}
})"
@click="$dispatch('swal:confirm', {
html: 'Delete {{ $genre->name }}?',
cancelButtonText: 'NO!',
confirmButtonText: 'YES DELETE THIS GENRE',
next: {
event: 'delete-genre',
params: {
id: {{ $genre->id }}
}
}
})"
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11