Discourse 3.1.0.beta6 wird mit einer brandneuen, komponentenbasierten <DModal>-API ausgeliefert. DModal ist Teil des UI-Kit und wird aus discourse/ui-kit/d-modal importiert.
Dies ersetzt die alte, controllerbasierte API, die nun veraltet ist. Wenn du bestehende Modals mit den alten APIs verwendest, findest du den Migrationsleitfaden hier.
Ein Modal rendern
Modals werden gerendert, indem die <DModal>-Komponente in eine Handlebars-Vorlage eingebunden wird. Falls du noch keine geeignete Vorlage hast, schau dir Using Plugin Outlet Connectors from a Theme or Plugin an.
Ein einfaches Modal könnte so aussehen:
<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}}
Der
mut-Helper wird hier als hbs-spezifische Methode verwendet, um einen Wert zu setzen. Du könntestmodalIsVisibleauch mit jeder anderen Standard-Ember-Methode setzen.
Dieses Beispiel erstellt ein einfaches Modal wie dieses:
In einer Komponente kapseln
Bevor weitere Komplexität eingeführt wird, ist es in der Regel am besten, das neue Modal in seiner eigenen Komponenten-Definition zu kapseln. Verschieben wir also das <DModal>-Gerüst in eine neue <MyModal />-Komponente.
// components/my-modal.gjs
<template>
<DModal @title="My Modal" @closeModal={{@closeModal}}>
Hello world, this is some content in a modal
</DModal>
</template>
Das Aufrüsten dieser .gjs-Datei zu einer klassenbasierten Komponente ermöglicht es dir, komplexere Logik und Zustände einzuführen.
Um die neue Komponente zu nutzen, aktualisiere die Aufrufstelle, um sie zu referenzieren, und achte darauf, ein @closeModal-Argument zu übergeben.
<DButton
@translatedLabel="Show Modal"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}
Ein Footer hinzufügen
Viele Modals haben eine Art Call-to-Action. In Discourse befinden sich diese tendenziell am unteren Rand des Modals. Um dies zu ermöglichen, verfügt DModal über eine Reihe von ‘benannten Blöcken’ (named blocks), in die Inhalte gerendert werden können. Hier ist das Beispiel aktualisiert, um zwei Buttons im Footer zu enthalten, wobei einer unser Standard-DModalCancel-Button ist.
<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>
Ein Modal aus einem Nicht-hbs-Kontext rendern
Idealerweise sollten <DModal>-Instanzen innerhalb einer Ember-Vorlage mit der oben demonstrierten deklarativen Technik gerendert werden. Falls dies für deinen Anwendungsfall nicht machbar ist, kann dies durch das Einspritzen des modal-Services und den Aufruf von modal.show() erledigt werden.
Stelle sicher, dass du dein Modal wie oben beschrieben in seiner eigenen Komponente gekapselt hast. Dann löst du das Modal aus, indem du eine Referenz auf deine Komponentenklasse an showModal übergibst:
import MyModal from "discourse/components/my-modal";
// (den modal-Service an der entsprechenden Stelle injizieren)
// Füge diesen Aufruf hinzu, wann immer du das Modal öffnen möchtest.
// Ein `@closeModal`-Argument wird deiner Komponente automatisch übergeben.
this.modal.show(MyModal);
// Optional: Übergib einen '`model`'-Parameter. Wird als `@model` an deine Komponente übergeben.
// Dies kann Daten sowie Aktionen/Callbacks enthalten, die dein Modal verwenden soll.
this.modal.show(MyModal, {
model: { topic: this.topic, someAction: this.someAction },
});
// `modal.show()` gibt ein Promise zurück, sodass du darauf warten kannst, dass es geschlossen wird.
// Es wird mit den Daten aufgelöst, die an die `@closeModal`-Aktion übergeben wurden.
const result = await this.modal.show(MyModal);
Mehr Anpassungsmöglichkeiten!
<DModal> verfügt über eine Reihe von benannten Blöcken und Argumenten.
Argumente
| Arg | Zweck |
|---|---|
@closeModal |
Erforderlich, damit überhaupt eine UI zum Schließen angezeigt wird. |
@title |
Rendert <h1 id="discourse-modal-title">; verdrahtet aria-labelledby. |
@subtitle |
Kleiner Text unter dem Titel. |
@flash / @flashType |
Inline-Warnung oben im Modal (DFlashMessage). |
@hideHeader, @hideFooter |
Versteckt ganze Bereiche. |
@headerClass, @bodyClass |
Zusätzliche Klasse auf den Header/Body-Wrapper. |
@dismissable |
Standardmäßig true, wenn @closeModal gesetzt ist. Deaktiviert Esc / Klick auf Hintergrund / X. |
@autofocus |
Standardmäßig true. Fokussiert automatisch das erste fokussierbare Element über dTrapTab. |
@submitOnEnter |
Standardmäßig true. Enter klickt .d-modal__footer .btn-primary, es sei denn, der Fokus liegt in einem Formular / Textarea / Select-Kit. |
@beforeClose |
async ({ initiatedBy }) => boolean. Gib false zurück, um das Schließen abzubrechen (z. B. Bestätigung bei ungespeicherten Änderungen). |
@hidden |
Pausiert die Tastaturverarbeitung; wird verwendet, wenn ein verschachteltes Modal darüber liegt. |
@tagName |
"div" (Standard) oder "form". Verwende "form" für Formulare, damit die native Submit-Funktion funktioniert. |
Blöcke
| Block | Position | Wann verwenden |
|---|---|---|
default / :body |
Hauptinhaltsbereich | Standardbereich |
:aboveHeader |
Ganz oben, vor dem Header | Selten benötigt; für Inhalte, die über der Titelleiste sitzen müssen (z. B. ein Banner). |
:headerAboveTitle |
Im Header, vor dem Titel | Vorhanden, aber ungenutzt. Selten benötigt. |
:belowModalTitle |
In .d-modal__title, nach dem <h1> |
Hervorragende Position für ergänzende Metainformationen. |
:headerBelowTitle |
Im Header, nach dem Titelblock | Tabs, Sub-Navigation oder Suchfeld, die Teil des Headers sind. |
:headerPrimaryAction |
Rechte Seite des Headers nur auf Mobilgeräten | Ersetzt den X-Schließen-Button durch eine primäre Aktion (z. B. “Speichern”). Rendert auch automatisch einen “Abbrechen”-Button links und fügt .--has-primary-action zum Header hinzu. |
:belowHeader |
Zwischen Header und Body | Persistenter Sub-Header-Inhalt (z. B. Suche), der außerhalb des scrollbaren Body liegt, für eine Sticky-Anzeige. |
:aboveFooter |
Zwischen Body und Footer | Unterdrückt, wenn @hideFooter gesetzt ist. Für Inhalte verwenden, die mit dem Footer zusammenhängen, aber außerhalb liegen. Ebenfalls selten. |
:footer |
Untere Aktionsleiste | Primäre + sekundäre Buttons. Der erste .btn-primary hier ist der, den Enter auslöst. |
:belowFooter |
Nach dem Footer | Selten benötigt; ignoriert @hideFooter. Nützlich für Status-Text außerhalb des gerahmten Footer-Bereichs. |
Quellen: der interaktive Styleguide für Argumente und die d-modal-Template-Implementierung für benannte Blöcke.
CSS
Verwende die .d-modal-Klassen als Anker, um Core zu überschreiben, und vermeide den Legacy-.modal-Selektor.
4 Modifikatoren verfügbar:
- .
--largesetzt die maximale Breite auf 800px (nur Desktop) - .
--maxsetzt die maximale Breite auf 90vw (nur Desktop) - .
has-searchsetzt eine feste Höhe (80vh): für Modals mit Such-/Filtersystem gedacht, um Höhenänderungen basierend auf der Ergebnislänge zu vermeiden (nur Desktop) .--stackedsetzt die Footer-Buttons auf gestapelte Ansicht (nur Mobilgeräte)
Dieses Dokument wird versioniert verwaltet - Vorschläge für Änderungen auf GitHub.

