Discourse 3.1.0.beta6 introduce una nuova API basata su componenti per <DModal>. DModal fa parte del UI kit e viene importato da discourse/ui-kit/d-modal.
Questa API sostituisce la vecchia API basata su controller, che è ora deprecata. Se hai modali esistenti che utilizzano le vecchie API, consulta la guida alla migrazione qui.
Rendering di un Modale
I modali vengono renderizzati includendo il componente <DModal> in un template handlebars. Se non hai già un template adatto, consulta Using Plugin Outlet Connectors from a Theme or Plugin.
Un semplice modale apparirebbe così:
<DButton
@translatedLabel="Show Modal"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<DModal @title="My Modal" @closeModal={{fn (mut this.modalIsVisible) false}}>
Hello world, this is some content in a modal
</DModal>
{{/if}}
Qui viene utilizzato l’helper
mutcome metodo esclusivo per hbs per impostare un valore. Potresti anche impostaremodalIsVisibleutilizzando qualsiasi altro metodo standard di Ember.
Questo esempio creerà un semplice Modale simile a questo:
Incapsulamento in un componente
Prima di introdurre ulteriore complessità, è generalmente meglio incapsulare il nuovo Modale in una propria definizione di Componente. Spostiamo la parte <DModal> all’interno di un nuovo componente <MyModal />
// components/my-modal.gjs
<template>
<DModal @title="My Modal" @closeModal={{@closeModal}}>
Hello world, this is some content in a modal
</DModal>
</template>
L’aggiornamento di questo file .gjs a un componente basato su classe ti consentirà di introdurre logiche e stati più complessi.
Per utilizzare il nuovo componente, aggiorna il punto di chiamata per fare riferimento ad esso, assicurandoti di passare un argomento @closeModal.
<DButton
@translatedLabel="Show Modal"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}
Aggiunta di un footer
Molti modali hanno una sorta di call-to-action. In Discourse, queste tendono a trovarsi nella parte inferiore del modale. Per rendere possibile ciò, DModal dispone di diversi ‘blocchi nominati’ in cui è possibile renderizzare contenuto. Ecco l’esempio aggiornato per includere due pulsanti nel footer, uno dei quali è il nostro standard pulsante DModalCancel
<DModal @title="My Modal" @closeModal={{@closeModal}}>
<:body>
Hello world, this is some content in a modal
</:body>
<:footer>
<DButton class="btn-primary" @translatedLabel="Submit" />
<DModalCancel @close={{@closeModal}} />
</:footer>
</DModal>
Rendering di un modale da un contesto non-hbs
Idealmente, le istanze di <DModal> dovrebbero essere renderizzate da un template Ember utilizzando la tecnica dichiarativa dimostrata sopra. Se ciò non è fattibile per il tuo caso d’uso, può essere fatto iniettando il servizio modal e chiamando modal.show().
Assicurati di aver incapsulato il tuo modale in un proprio componente come descritto sopra. Quindi, attiva il modale passando un riferimento della tua classe componente a showModal:
import MyModal from "discourse/components/my-modal";
// (inietta il servizio modal nel punto rilevante)
// Aggiungi questa chiamata ogni volta che vuoi aprire il modale.
// Un argomento `@closeModal` verrà passato automaticamente al tuo componente.
this.modal.show(MyModal);
// Facoltativamente, passa un parametro '`model`'. Viene passato come `@model` al tuo componente.
// Questo può includere dati e anche azioni/callback per il tuo Modale da utilizzare.
this.modal.show(MyModal, {
model: { topic: this.topic, someAction: this.someAction },
});
// `modal.show()` restituisce una promise, quindi puoi aspettare che venga chiuso
// Si risolverà con i dati passati all'azione `@closeModal`
const result = await this.modal.show(MyModal);
Più personalizzabilità!
<DModal> ha una serie di blocchi nominati e argomenti.
Argomenti
| Arg | Scopo |
|---|---|
@closeModal |
Obbligatorio affinché l’UI di chiusura venga visualizzata. |
@title |
Renderizza <h1 id="discourse-modal-title">; collega aria-labelledby. |
@subtitle |
Testo piccolo sotto il titolo. |
@flash / @flashType |
Alert inline in alto nel modale (DFlashMessage). |
@hideHeader, @hideFooter |
Nasconde le intere regioni. |
@headerClass, @bodyClass |
Classe aggiuntiva sui wrapper di header/body. |
@dismissable |
Predefinito true quando @closeModal è impostato. Disabilita Esc / clic sullo sfondo / X. |
@autofocus |
Predefinito true. Mette a fuoco automaticamente il primo elemento focalizzabile tramite dTrapTab. |
@submitOnEnter |
Predefinito true. Enter fa clic su .d-modal__footer .btn-primary a meno che il focus non sia in un form / textarea / select-kit. |
@beforeClose |
async ({ initiatedBy }) => boolean. Restituisce false per annullare la chiusura (es. conferma form sporco). |
@hidden |
Sospende la gestione della tastiera; usato quando un modale annidato è in cima. |
@tagName |
"div" (predefinito) o "form". Usa "form" per i form in modo che il submit nativo funzioni. |
Blocchi
| Block | Posizione | Quando usarlo |
|---|---|---|
default / :body |
Area di contenuto principale | Area predefinita |
:aboveHeader |
Molto in alto, prima dell’header | Raramente necessario; per contenuto che deve trovarsi sopra la barra del titolo (es. un banner). |
:headerAboveTitle |
All’interno dell’header, prima del titolo | Presente ma non utilizzato. Raramente necessario. |
:belowModalTitle |
All’interno di .d-modal__title, dopo l’<h1> |
Posizione eccellente per informazioni meta supplementari. |
:headerBelowTitle |
All’interno dell’header, dopo il blocco titolo | Tab, sub-nav o campo di ricerca che fa parte dell’header. |
:headerPrimaryAction |
Lato destro dell’header solo su mobile | Sostituisce il pulsante di chiusura X con un’azione primaria (es. “Salva”). Renderizza anche automaticamente un pulsante “Annulla” a sinistra e aggiunge .--has-primary-action all’header. |
:belowHeader |
Tra header e body | Contenuto di sub-header persistente (es. ricerca) che è esterno al body scorrevole, per un display sticky. |
:aboveFooter |
Tra body e footer | Soppresso quando @hideFooter è impostato. Usa per contenuto legato al footer ma esterno ad esso. Anche raro. |
:footer |
Barra di azione inferiore | Pulsanti primari + secondari. Il primo .btn-primary qui è ciò che viene attivato da Enter. |
:belowFooter |
Dopo il footer | Raramente necessario; ignora @hideFooter. Utile per testo di stato esterno all’area del footer con bordo. |
Fonti: la styleguide interattiva per gli argomenti, e l’implementazione del template d-modal per i blocchi nominati.
CSS
Usa le classi .d-modal come punto di riferimento per sovrascrivere il core ed evita il selettore legacy .modal.
4 modificatori disponibili:
- .
--largeimposta la larghezza massima a 800px (solo desktop) - .
--maximposta la larghezza massima a 90vw (solo desktop) - .
has-searchimposta l’altezza fissa (80vh): destinato a modali con sistema di ricerca/filtri per evitare variazioni di altezza basate sulla lunghezza dei risultati (solo desktop) .--stackedimposta i pulsanti del footer in impilamento (solo mobile)
Questo documento è versionato - suggerisci modifiche su github.

