Un jolie système de notifications avec SweetAlert2

Tutoriel Symfony 6 - Un jolie système de notifications avec SweetAlert2

À propos de ce tutoriel

Je vous montre comment intégrer la librarie SweetAlert2 dans un projet Symfony 6 à travers plusieurs exemples concrets.

Création du projet

Dans un premier temps, il nous faut créer le projet :

symfony console new sweet_alert --webapp

Création du contrôleur HomeController

Nous allons créer notre unique contrôleur : HomeController.php.

C’est ici que nous allons implémenter nos routes afin de tester SweetAlert2.

symfony console make:controller Home
class HomeController extends AbstractController
{
    const SAFE_DEPOSIT_BOX_PASSWORD = 'TEST_1234';

    #[Route('/', name: 'app_home')]
    public function index(): Response
    {
        return $this->render('home/index.html.twig');
    }

    #[Route('/safe-deposit-box', name: 'app_safe_deposit_box')]
    public function safeDepositBox(Request $request): Response
    {
        $password = $request->request->get('password');

        return $this->json([
            'result' => $password === self::SAFE_DEPOSIT_BOX_PASSWORD
        ]);
    }
}

Création de nos vues Twig

{% extends 'base.html.twig' %}

{% block title %}Accueil{% endblock %}

{% block body %}
    <div class="container my-5">
        <div class="row">

            <div class="col-xl-4 mb-5">
                {% include 'home/_card.html.twig'
                    with {
                    'header': 'Coffre-fort',
                    'text': 'Le coffre-fort est protégé par un mot de passe',
                    'buttonClass': 'safeDepositBoxBtn',
                    'buttonText': 'Accéder au coffre-fort'
                } %}
            </div>

            <div class="col-xl-4 mb-5">
                {% include 'home/_card.html.twig'
                    with {
                    'header': "S'inscrire",
                    'text': 'Inscription gratuite',
                    'buttonClass': 'registerBtn',
                    'buttonText': "S'inscrire"
                } %}
            </div>

            <div class="col-xl-4">
                {% include 'home/_card.html.twig'
                    with {
                    'header': "Changer la couleur de l'arrière-plan",
                    'text': "Changer la couleur de l'arrière-plan",
                    'buttonClass': 'changeBackgroundColorBtn',
                    'buttonText': "Changer la couleur"
                } %}
            </div>

        </div>
    </div>

    {% include 'home/_template.html.twig' %}
{% endblock %}
<div class="card text-center">
    <div class="card-header">
        {{ header }}
    </div>
    <div class="card-body">
        <p class="card-text">{{ text }}</p>
        <a href="#" class="btn btn-primary {{ buttonClass }}">{{ buttonText }}</a>
    </div>
</div>
<template id="bg-color-template">
    <swal-title>Choisis une couleur</swal-title>
    <swal-icon type="question"></swal-icon>
    <swal-button type="confirm">Confirmer</swal-button>
    <swal-input type="text" placeholder="#fff"></swal-input>
</template>

Le code JavaScript

import '../css/app.scss';
import Swal from 'sweetalert2'

document.addEventListener('DOMContentLoaded', async () => {
    new App();
});

class App {
    /**
     * @type {HTMLElement}
     */
    body;
    /**
     * @type {HTMLButtonElement}
     */
    safeDepositBoxBtn;

    /**
     * @type {HTMLButtonElement}
     */
    registerBtn;

    /**
     * @type {HTMLButtonElement}
     */
    changeBackgroundColorBtn;

    constructor() {
        this.body = document.body;
        this.safeDepositBoxBtn = document.querySelector('.safeDepositBoxBtn');
        this.registerBtn = document.querySelector('.registerBtn');
        this.changeBackgroundColorBtn = document.querySelector('.changeBackgroundColorBtn');

        this.safeDepositBoxBtn.addEventListener('click', async () => {
            await this.openSafeDepositBox();
        });

        this.registerBtn.addEventListener('click', async () => {
            await this.register();
        });

        this.changeBackgroundColorBtn.addEventListener('click', async () => {
            this.body.style.backgroundColor = await this.changeBackgroundColor()
        });
    }

    async openSafeDepositBox() {
        const {value: password} = await Swal.fire({
            title: 'Ouverture du coffre-fort',
            confirmButtonText: 'Ouvrir',
            input: 'password',
            inputLabel: 'Mot de passe',
            inputPlaceholder: 'Entre le mot de passe du coffre-fort',
            inputAttributes: {
                minLength: 3,
                maxlength: 10,
                autocapitalize: 'off',
                autocorrect: 'off',
                required: true
            },
            validationMessage: 'Le mot de passe doit contenir entre 3 et 10 caractères !'
        });

        if (!password) {
            return;
        }

        const formData = new FormData();
        formData.append('password', password);

        const response = await fetch('/safe-deposit-box', {
            body: formData,
            method: 'POST'
        });

        const data = await response.json();

        if (data.result) {
            await Swal.fire({
                title: 'Félicitations',
                text: 'Le coffre est ouvert !',
                icon: 'success',
                confirmButtonColor: 'green'
            });
        } else {
            await Swal.fire({
                title: 'Erreur',
                text: "Ce n'est pas le bon mot de passe !",
                icon: 'error',
                confirmButtonColor: 'red'
            });
        }
    }

    async register() {
        const Toast = Swal.mixin({
            toast: true,
            position: 'top-end',
            showConfirmButton: false,
            timer: 3000,
            timerProgressBar: true,
            didOpen: (toast) => {
                toast.addEventListener('mouseenter', Swal.stopTimer)
                toast.addEventListener('mouseleave', Swal.resumeTimer)
            }
        })

        await Toast.fire({
            icon: 'success',
            title: 'Inscription réussie'
        })
    }

    async changeBackgroundColor() {
        const {value: color} = await Swal.fire({
            template: '#bg-color-template',
            inputAttributes: {
                minLength: 4,
                maxlength: 7,
                required: true
            },
            validationMessage: "Il ne s'agit pas d'une couleur hexadecimal !"
        });

        return color;
    }
}