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, auf Controllern basierende API, die nun als veraltet gilt. Wenn du bestehende Modals mit den alten APIs verwendest, findest du den Migrationsleitfaden hier.
Rendern eines Modals
Modals werden gerendert, indem die <DModal>-Komponente in einer Handlebars-Vorlage enthalten wird. Wenn du noch keine geeignete Vorlage hast, schaue dir Using Plugin Outlet Connectors from a Theme or Plugin an.
Ein einfaches Modal könnte etwa 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:
Einbetten in eine Komponente
Bevor weitere Komplexität eingeführt wird, ist es in der Regel am besten, das neue Modal in seiner eigenen Komponentendefinition zu kapseln. Verschieben wir den <DModal>-Teil 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 verwenden, aktualisiere die Aufrufstelle, damit sie darauf verweist, 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}}
Hinzufügen einer Fußzeile
Viele Modals haben eine Art Handlungsaufforderung (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 in der Fußzeile zu enthalten, von denen 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>
Rendern eines Modals aus einem Nicht-hbs-Kontext
Idealerweise sollten <DModal>-Instanzen innerhalb einer Ember-Vorlage gerendert werden, indem die oben demonstrierte deklarative Technik verwendet wird. Wenn das für deinen Anwendungsfall nicht machbar ist, kann dies durch Injizieren des modal-Services und Aufrufen 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";
// (injiziere den modal-Service an der relevanten Stelle)
// 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: Übergebe einen '`model`'-Parameter. Wird als `@model` an deine Komponente übergeben.
// Dies kann Daten und auch 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, daher kannst du darauf warten, 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 Anpassungsfähigkeit!
<DModal> verfügt über eine Reihe von benannten Blöcken und Argumenten.
Argumente
| Arg | Zweck |
|---|---|
@closeModal |
Erforderlich, damit die UI zum Schließen überhaupt angezeigt wird. |
@title |
Rendert <h1 id="discourse-modal-title">; verdrahtet aria-labelledby. |
@subtitle |
Kleiner Text unter dem Titel. |
@flash / @flashType |
Inline-Warnung am oberen Rand des Modals (DFlashMessage). |
@hideHeader, @hideFooter |
Versteckt ganze Bereiche. |
@headerClass, @bodyClass |
Zusätzliche Klasse für 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 / Textbereich / Select-Kit. |
@beforeClose |
async ({ initiatedBy }) => boolean. Gib false zurück, um das Schließen abzubrechen (z. B. Bestätigung bei schmutzigem Formular). |
@hidden |
Pausiert die Tastatursteuerung; wird verwendet, wenn ein verschachteltes Modal darüber liegt. |
@tagName |
"div" (Standard) oder "form". Verwende "form" für Formulare, damit das native Absenden funktioniert. |
Blöcke
| Block | Position | Wann zu 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 |
Innerhalb von .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 feste Anzeige. |
:aboveFooter |
Zwischen Body und Footer | Unterdrückt, wenn @hideFooter gesetzt ist. Verwende für Inhalte, die mit der Fußzeile verbunden sind, aber außerhalb liegen. Ebenfalls selten. |
:footer |
Untere Aktionsleiste | Primäre + sekundäre Buttons. Der erste .btn-primary hier ist der, der durch Enter ausgelöst wird. |
:belowFooter |
Nach der Fußzeile | Selten benötigt; ignoriert @hideFooter. Nützlich für Statuszeilen außerhalb des gerahmten Fußzeilenbereichs. |
Quellen: der interaktive Styleguide für Argumente und die d-modal-Vorlagendurchführung für benannte Blöcke.
CSS
Verwende die .d-modal-Klassen als Anker, um das Core-Design 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 die 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 Anordnung (nur Mobilgeräte)
Dieses Dokument ist versioniert - schlage Änderungen auf GitHub vor.

