Discourse 3.1.0.beta6 intègre une toute nouvelle API basée sur les composants <DModal>.
Cette nouvelle API remplace l’ancienne API basée sur les contrôleurs, qui est désormais obsolète. Si vous utilisez encore des modales avec l’ancienne API, consultez le guide de migration ici.
Affichage d’une modale
Les modales sont affichées en incluant le composant <DModal> dans un modèle Handlebars. Si vous ne disposez pas encore d’un modèle approprié, consultez Using Plugin Outlet Connectors from a Theme or Plugin.
Une modale simple ressemblerait à ceci :
<DButton
@translatedLabel="Afficher la modale"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<DModal @title="Ma modale" @closeModal={{fn (mut this.modalIsVisible) false}}>
Bonjour le monde, voici du contenu dans une modale
</DModal>
{{/if}}
L’helper
mutest utilisé ici comme une méthode spécifique à hbs pour définir une valeur. Vous pouvez également définirmodalIsVisibleen utilisant n’importe quelle autre méthode standard d’Ember.
Cet exemple créera une modale simple comme celle-ci :
Encapsulation dans un composant
Avant d’introduire plus de complexité, il est généralement préférable d’encapsuler votre nouvelle modale dans sa propre définition de composant. Déplaçons le contenu de <DModal> dans un nouveau composant <MyModal />.
// components/my-modal.gjs
<template>
<DModal @title="Ma modale" @closeModal={{@closeModal}}>
Bonjour le monde, voici du contenu dans une modale
</DModal>
</template>
Mettre à jour ce fichier .gjs vers un composant basé sur une classe vous permettra d’introduire une logique et un état plus complexes.
Pour utiliser le nouveau composant, mettez à jour l’appel pour le référencer, en veillant à transmettre un argument @closeModal.
<DButton
@translatedLabel="Afficher la modale"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}
Ajout d’un pied de page
De nombreuses modales comportent une sorte d’appel à l’action. Dans Discourse, celles-ci sont généralement situées en bas de la modale. Pour rendre cela possible, DModal dispose de plusieurs « blocs nommés » dans lesquels du contenu peut être rendu. Voici l’exemple mis à jour pour inclure deux boutons dans le pied de page, dont l’un est notre bouton standard DModalCancel.
<DModal @title="Ma modale" @closeModal={{@closeModal}}>
<:body>
Bonjour le monde, voici du contenu dans une modale
</:body>
<:footer>
<DButton class="btn-primary" @translatedLabel="Soumettre" />
<DModalCancel @close={{@closeModal}} />
</:footer>
</DModal>
Affichage d’une modale depuis un contexte non hbs
Idéalement, les instances de <DModal> doivent être affichées depuis un modèle Ember en utilisant la technique déclarative démontrée ci-dessus. Si cela n’est pas réalisable pour votre cas d’utilisation, cela peut être fait en injectant le service modal et en appelant modal.show().
Assurez-vous d’avoir encapsulé votre modale dans son propre composant comme décrit ci-dessus. Ensuite, déclenchez la modale en passant une référence de votre classe de composant à showModal :
import MyModal from "discourse/components/my-modal";
// (injectez le service modal à l'endroit approprié)
// Ajoutez cet appel chaque fois que vous souhaitez ouvrir la modale.
// Un argument `@closeModal` sera automatiquement transmis à votre composant.
this.modal.show(MyModal);
// Optionnellement, passez un paramètre `model`. Transmis sous forme de `@model` à votre composant.
// Cela peut inclure des données, ainsi que des actions/rappels pour votre modale à utiliser.
this.modal.show(MyModal, {
model: { topic: this.topic, someAction: this.someAction },
});
// `modal.show()` retourne une promesse, vous pouvez donc attendre sa fermeture.
// Elle sera résolue avec les données transmises à l'action `@closeModal`.
const result = await this.modal.show(MyModal);
Plus de personnalisation !
<DModal> dispose de plusieurs blocs nommés et arguments.
Arguments
| Argument | Objectif |
|---|---|
@closeModal |
Requis pour que l’interface de fermeture apparaisse. |
@title |
Affiche <h1 id="discourse-modal-title"> ; lie aria-labelledby. |
@subtitle |
Petit texte sous le titre. |
@flash / @flashType |
Alerte en ligne en haut de la modale (DFlashMessage). |
@hideHeader, @hideFooter |
Cache les régions entières. |
@headerClass, @bodyClass |
Classes supplémentaires sur les wrappers du header/body. |
@dismissable |
Par défaut true lorsque @closeModal est défini. Désactive Échap / clic sur le fond / X. |
@autofocus |
Par défaut true. Met automatiquement le focus sur le premier élément focusable via dTrapTab. |
@submitOnEnter |
Par défaut true. La touche Entrée clique sur .d-modal__footer .btn-primary sauf si le focus est dans un formulaire / textarea / select-kit. |
@beforeClose |
async ({ initiatedBy }) => boolean. Retournez false pour annuler la fermeture (par exemple, confirmation de formulaire modifié). |
@hidden |
Met en pause la gestion du clavier ; utilisé lorsqu’une modale imbriquée est au premier plan. |
@tagName |
"div" (par défaut) ou "form". Utilisez "form" pour les formulaires afin que la soumission native fonctionne. |
Blocs
| Bloc | Position | Quand l’utiliser |
|---|---|---|
default / :body |
Zone de contenu principale | Zone par défaut |
:aboveHeader |
Tout en haut, avant l’en-tête | Rarement nécessaire ; pour le contenu qui doit se situer au-dessus de la barre de titre (par exemple, une bannière). |
:headerAboveTitle |
Dans l’en-tête, avant le titre | Présent mais inutilisé. Rarement nécessaire. |
:belowModalTitle |
Dans .d-modal__title, après le <h1> |
Excellente position pour des métadonnées supplémentaires. |
:headerBelowTitle |
Dans l’en-tête, après le bloc titre | Onglets, sous-navigation ou champ de recherche faisant partie de l’en-tête. |
:headerPrimaryAction |
Côté droit de l’en-tête uniquement sur mobile | Remplace le bouton de fermeture X par une action principale (par exemple, « Enregistrer »). Affiche également automatiquement un bouton « Annuler » à gauche et ajoute .--has-primary-action à l’en-tête. |
:belowHeader |
Entre l’en-tête et le corps | Contenu de sous-en-tête persistant (par exemple, recherche) qui se trouve en dehors du corps défilant, pour un affichage fixe. |
:aboveFooter |
Entre le corps et le pied de page | Supprimé lorsque @hideFooter est défini. À utiliser pour le contenu lié au pied de page mais en dehors de celui-ci. Également rare. |
:footer |
Barre d’action en bas | Boutons principaux et secondaires. Le premier .btn-primary ici est celui que la touche Entrée déclenche. |
:belowFooter |
Après le pied de page | Rarement nécessaire ; ignore @hideFooter. Utile pour le texte de statut en dehors de la zone bordée du pied de page. |
Sources : le guide de style interactif pour les arguments, et l’implémentation du modèle d-modal pour les blocs nommés.
CSS
Utilisez les classes .d-modal comme ancre pour remplacer le noyau, et évitez le sélecteur hérité .modal.
4 modificateurs disponibles :
.--largedéfinit la largeur maximale à 800px (uniquement sur bureau).--maxdéfinit la largeur maximale à 90vw (uniquement sur bureau).has-searchdéfinit la hauteur fixe (80vh) : destiné aux modales avec un système de recherche/filtre pour éviter un changement de hauteur basé sur la longueur des résultats (uniquement sur bureau).--stackeddéfinit les boutons du pied de page en empilement (uniquement sur mobile)
Ce document est versionné — proposez des modifications sur GitHub.

