angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Flask Message Flashing : Remplacer Bootstrap Alerts par Toasts

Afficher les notifications à une position fixe, au-dessus du contenu de l'écran, et non pas à un endroit où elles sont comprimées dans notre mise en page.

25 juillet 2022
post main image
https://www.pexels.com/nl-nl/@goumbik

Lorsque vous avez une application Flask avec Bootstrap, vous utilisez probablement Bootstrap Alerts pour afficher flashed messages. Je les utilise, et ils fonctionnent, mais je ne suis pas vraiment satisfait. Par défaut, elles ne sont pas jolies et, dans la plupart des cas, elles prennent beaucoup de place sur l'écran. Et voulez-vous vraiment que des notifications comme "vous êtes connecté" soient une Bootstrap Alert qui doit être fermée par la user ? En ajoutant un délai d'attente, nous pouvons supprimer automatiquement la Bootstrap Alert mais c'est encore plus moche !

Bootstrap Toasts

Avec Bootstrap Toasts , nous pouvons créer des notifications qui sont placées à une position fixe au-dessus du contenu de l'écran, et non pas quelque part dans notre mise en page. Nous utilisons 'position-fixed' dans 'toast-container' pour rendre la toast visible dans la viewport. J'ai placé ma toasts en haut à droite mais avec un certain décalage par rapport au haut de l'écran. J'ai également dû augmenter la valeur de 'z-index' pour être sûr que la toast soit toujours en haut.

<style>
.toast-container-extra {
    top: 30px;
    z-index: 10000;
}
</style>

Si vous avez plusieurs toasts, vous ne voulez probablement pas que les toasts soient superposés, mais empilés :

  • La deuxième toast est présentée sous la première.
  • La troisième toast est présentée sous la deuxième.
  • Etc.

Cela signifie que lorsque nous voulons afficher un toast, nous avons besoin d'un code Javascript / JQuery pour :

  • Créer le toast HTML à partir d'un modèle.
  • Ajouter le message toast
  • Ajoutez le toast HTML à notre toast-container
  • Dites à Bootstrap que nous avons un nouveau toast.
  • Faites en sorte que Bootstrap affiche la toast.

Vous utilisez probablement déjà les Flask Message Flashing avec des catégories :

flash('Invalid password provided', 'error')
...
flash('Invalid password provided', 'info')

J'ai défini ci-dessous le modèle toast-container et deux modèles toast , un modèle pour la catégorie 'error' et un modèle pour la catégorie 'info'. Le 'error' toast nécessite le user pour le fermer, le 'info' toast se ferme automatiquement après quelques secondes.
Le modèle de catégorie est identifié par l'attribut 'data-stack-toast-category', nous voulons éviter les doublons.

{# stacked toasts container - start #}
<div class="toast-container position-fixed end-0 p-3 pt-0 toast-container-extra" id="toast-stack-container">
</div>
{# stacked toasts container - end #}

{# stacked toast error template - start #}
<div 
    class="toast mt-0" 
    role="alert" 
    aria-live="assertive" 
    aria-atomic="true" 
    data-bs-autohide="false"
    data-stack-toast-category="error">
    <div class="toast-header border-bottom border-white">
        <strong class="me-auto">
            Error
        </strong>
        <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
    </div>
    <div class="toast-body toast-message"></div>
</div>
{# stacked toast error template - end #}

{# stacked toast info template - start #}
<div class="toast mt-0" 
    role="status"
    aria-live="polite"
    aria-atomic="true"
    data-stack-toast-category="info">
    <div class="toast-header border-bottom border-white">
        <strong class="me-auto">
            Info
        </strong>
        <button type="button"  class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
    </div>
    <div class="toast-body toast-message"></div>
</div>
{# stacked toast info template - end #}

Voici le code pour ajouter un toast, à ajouter au fichier Javascript de votre site web :

const toast_stack_container_elem = document.getElementById('toast-stack-container');
const error_toast_template_elem = document.querySelector('[data-stack-toast-category="error"]');
const info_toast_template_elem = document.querySelector('[data-stack-toast-category="info"]');

function create_toast_add_to_stack(category, message){
    var new_toast;
    switch(category){
    case 'error':
        new_toast = error_toast_template_elem.cloneNode(true);
        break;
    default:
        new_toast = info_toast_template_elem.cloneNode(true);
    }
    var toast_message_elem = new_toast.querySelector('.toast-message');
    if(toast_message_elem){
        toast_message_elem.innerHTML = message;
    }
    toast_stack_container_elem.append(new_toast);
    const toast = bootstrap.Toast.getOrCreateInstance(new_toast);
    toast.show();
    return;
}

Maintenant, vous voulez probablement ajouter deux boutons "Afficher toast" et du code pour vérifier que cela fonctionne.

Modifier le modèle de base

Vous avez probablement un modèle de base avec quelque chose comme le code suivant pour afficher les alertes flashed messages avec Bootstrap :

{% with messages = get_flashed_messages(with_categories=true) -%}
    {% for category, message in messages -%}
        {% if category == 'error' -%}
            {% set alert_class = 'alert-danger' -%}
        {% else -%}
            {% set alert_class = 'alert-info' -%}
        {% endif -%}
        <div class="alert {{ alert_class }} alert-dismissible mb-3" role="alert">
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
            {{ message }}
        </div>
    {% endfor -%}
{% endwith -%}

Pour utiliser Bootstrap toasts, nous modifions ce code . J'utilise ici JSON pour éviter les erreurs Content Security Policy (CSP).

{% with messages = get_flashed_messages(with_categories=true) -%}

{% set flashed_messages_page_data_js={} -%}
{% set x=flashed_messages_page_data_js.__setitem__('messages', messages) -%}
<script type="application/json" data-selector="flashed-messages-page-data-js">
{{ flashed_messages_page_data_js|tojson }}
</script>            

{% endwith -%}

Et ensuite, ajoutez le code suivant au fichier Javascript de votre site web :

$(document).ready(function(){
    try {
        if($('script[data-selector="flashed-messages-page-data-js"]').length){
            var flashed_messages_page_data_js = JSON.parse($('script[data-selector="flashed-messages-page-data-js"]').html());
            if(flashed_messages_page_data_js.hasOwnProperty('messages')){
                var messages = flashed_messages_page_data_js.messages;
                for(var i = 0; i < messages.length; i++){
                    var category = messages[i][0];
                    var message = messages[i][1];
                    create_toast_add_to_stack(category, message);
                }
            }
        }
    }
    catch(error){
        // no-op
        console.log('flashed messages, error = ');
        console.log(error);
    }    

});

Résumé

Nous avons remplacé Bootstrap Alerts par Bootstrap Toasts par Flask Message Flashing. C'est bien, mais nous voulons probablement un contrôle plus fin. Nous pourrions ajouter des catégories supplémentaires pour les cas où nous voulons toujours des alertes Bootstrap , par exemple :

  • "alerte-erreur
  • alerte-info

Nous pouvons également remplacer la fonction "flash()" et ajouter des paramètres tels que :

  • notification_type
  • auto_hide

Mais avant de réinventer la roue, nous devrions d'abord vérifier comment les notifications et les alertes sont affichées sur les téléphones portables. Une autre fois ...

Liens / crédits

Bootstrap - Alerts
https://getbootstrap.com/docs/5.1/components/alerts

Bootstrap - Toasts
https://getbootstrap.com/docs/5.2/components/toasts

Flask - Message Flashing
https://flask.palletsprojects.com/en/2.1.x/patterns/flashing

Inline Data With a Content Security Policy
https://itnext.io/inline-data-with-a-content-security-policy-ab30dde2feb3

Toasts
https://preview.keenthemes.com/start/documentation/base/toasts.html

Laissez un commentaire

Commentez anonymement ou connectez-vous pour commenter.

Commentaires

Laissez une réponse

Répondez de manière anonyme ou connectez-vous pour répondre.