Discourse 3.1.0.beta6 bringt eine brandneue, komponentenbasierte API für <DModal> mit.
Diese ersetzt die alte controller-basierte API, die nun als veraltet gilt. Falls Sie bestehende Modals mit den alten APIs verwenden, werfen Sie einen Blick auf den Migrationsleitfaden hier.
Ein Modal rendern
Modals werden gerendert, indem die <DModal>-Komponente in einer Handlebars-Vorlage eingebunden wird. Falls Sie noch keine geeignete Vorlage haben, schauen Sie sich Using Plugin Outlet Connectors from a Theme or Plugin an.
Ein einfaches Modal sieht ungefähr so aus:
<DButton
@translatedLabel="Modal anzeigen"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<DModal @title="Mein Modal" @closeModal={{fn (mut this.modalIsVisible) false}}>
Hallo Welt, dies ist etwas Inhalt in einem Modal
</DModal>
{{/if}}
Der
mut-Helper wird hier als hbs-spezifische Möglichkeit verwendet, einen Wert zu setzen. Sie könntenmodalIsVisibleauch mit jeder anderen Standard-Ember-Methode setzen.
Dieses Beispiel erstellt ein einfaches Modal wie dieses:
In eine Komponente einpacken
Bevor Sie weitere Komplexität einführen, ist es meist am besten, Ihr neues Modal in eine eigene Komponentendefinition zu verpacken. Verschieben wir den <DModal>-Teil in eine neue <MyModal />-Komponente.
// components/my-modal.gjs
<template>
<DModal @title="Mein Modal" @closeModal={{@closeModal}}>
Hallo Welt, dies ist etwas Inhalt in einem Modal
</DModal>
</template>
Das Aktualisieren dieser .gjs-Datei zu einer klassenbasierten Komponente ermöglicht es Ihnen, komplexere Logik und Zustände einzuführen.
Um die neue Komponente zu nutzen, aktualisieren Sie die Aufrufstelle, um darauf zu verweisen, und stellen Sie sicher, dass Sie ein @closeModal-Argument übergeben.
<DButton
@translatedLabel="Modal anzeigen"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}
Einen Footer hinzufügen
Viele Modals haben eine Art Handlungsaufforderung. In Discourse befinden sich diese tendenziell am unteren Rand des Modals. Um dies zu ermöglichen, verfügt DModal über mehrere „benannte Blöcke“, in die Inhalte gerendert werden können. Hier ist das aktualisierte Beispiel mit zwei Buttons im Footer, wobei einer davon unser Standard-DModalCancel-Button ist:
<DModal @title="Mein Modal" @closeModal={{@closeModal}}>
<:body>
Hallo Welt, dies ist etwas Inhalt in einem Modal
</:body>
<:footer>
<DButton class="btn-primary" @translatedLabel="Absenden" />
<DModalCancel @close={{@closeModal}} />
</:footer>
</DModal>
Ein Modal aus einem Nicht-HBS-Kontext rendern
Idealerweise sollten <DModal>-Instanzen innerhalb einer Ember-Vorlage mit der oben gezeigten deklarativen Technik gerendert werden. Falls dies für Ihren Anwendungsfall nicht machbar ist, kann dies durch Einbinden des modal-Services und Aufrufen von modal.show() erfolgen.
Stellen Sie sicher, dass Sie Ihr Modal wie oben beschrieben in eine eigene Komponente verpackt haben. Lösen Sie das Modal dann aus, indem Sie einen Verweis auf Ihre Komponentenklasse an showModal übergeben:
import MyModal from "discourse/components/my-modal";
// (den modal-Service an der relevanten Stelle einbinden)
// Rufen Sie dies immer auf, wenn Sie das Modal öffnen möchten.
// Ein `@closeModal`-Argument wird automatisch an Ihre Komponente übergeben.
this.modal.show(MyModal);
// Optional: Übergeben Sie einen `model`-Parameter. Wird als `@model` an Ihre Komponente übergeben.
// Dies kann Daten sowie Aktionen/Rückrufe enthalten, die Ihr Modal verwenden kann.
this.modal.show(MyModal, {
model: { topic: this.topic, someAction: this.someAction },
});
// `modal.show()` gibt ein Promise zurück, sodass Sie auf das Schließen warten können.
// Es wird mit den Daten aufgelöst, die an die `@closeModal`-Aktion übergeben wurden.
const result = await this.modal.show(MyModal);
Noch mehr Anpassungsmöglichkeiten!
<DModal> verfügt über mehrere benannte Blöcke und Argumente.
Argumente
| Arg | Zweck |
|---|---|
@closeModal |
Erforderlich, damit die Schließen-UI überhaupt angezeigt wird. |
@title |
Rendert <h1 id="discourse-modal-title">; verknüpft aria-labelledby. |
@subtitle |
Kleiner Text unter der Überschrift. |
@flash / @flashType |
Inline-Warnung am oberen Rand des Modals (DFlashMessage). |
@hideHeader, @hideFooter |
Ganze Bereiche ausblenden. |
@headerClass, @bodyClass |
Zusätzliche Klasse für Header-/Body-Umhüllungen. |
@dismissable |
Standardmäßig true, wenn @closeModal gesetzt. Deaktiviert Esc / Klick auf Hintergrund / X. |
@autofocus |
Standardmäßig true. Fokussiert automatisch das erste fokussierbare Element über dTrapTab. |
@submitOnEnter |
Standardmäßig true. Enter klickt auf .d-modal__footer .btn-primary, es sei denn, der Fokus liegt in einem Formular / Textfeld / Select-Kit. |
@beforeClose |
async ({ initiatedBy }) => boolean. Geben Sie false zurück, um das Schließen abzubrechen (z. B. bei Dirty-Form-Bestätigung). |
@hidden |
Pausiert die Tastaturbehandlung; wird verwendet, wenn sich ein verschachteltes Modal darüber befindet. |
@tagName |
"div" (Standard) oder "form". Verwenden Sie "form" für Formulare, damit die native Einreichung funktioniert. |
Blöcke
| Block | Position | Wann zu verwenden |
|---|---|---|
default / :body |
Hauptinhaltsbereich | Standardbereich |
:aboveHeader |
Ganz oben, vor dem Header | Selten erforderlich; für Inhalte, die über der Titelleiste sitzen müssen (z. B. ein Banner). |
:headerAboveTitle |
Im Header, vor der Überschrift | Vorhanden, aber ungenutzt. Selten erforderlich. |
:belowModalTitle |
In .d-modal__title, nach dem <h1> |
Ausgezeichnete Position für zusätzliche Metainformationen. |
:headerBelowTitle |
Im Header, nach dem Titelblock | Tabs, Unter-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 Hauptaktion (z. B. „Speichern“). Rendert automatisch einen „Abbrechen“-Button links und fügt .--has-primary-action zum Header hinzu. |
:belowHeader |
Zwischen Header und Body | Persistenter Subheader-Inhalt (z. B. Suche), der außerhalb des scrollbaren Bodies liegt, also für eine feste Anzeige. |
:aboveFooter |
Zwischen Body und Footer | Unterdrückt, wenn @hideFooter gesetzt ist. Verwenden Sie dies für Inhalte, die mit dem Footer verbunden, aber außerhalb davon sind. Auch selten. |
:footer |
Untere Aktionsleiste | Primäre + sekundäre Buttons. Der erste .btn-primary hier ist das, was Enter auslöst. |
:belowFooter |
Nach dem Footer | Selten erforderlich; ignoriert @hideFooter. Nützlich für Status-Text außerhalb des umrandeten Footer-Bereichs. |
Quellen: der interaktive Styleguide für Argumente und die d-modal-Vorlagenimplementierung für benannte Blöcke.
CSS
Verwenden Sie die .d-modal-Klassen als Anker, um das Core-Design zu überschreiben, und vermeiden Sie den veralteten .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): gedacht für Modals mit Such-/Filtersystem, um eine Höhenänderung basierend auf der Ergebnislänge zu vermeiden (nur Desktop).--stackedsetzt Footer-Buttons auf Stapelung (nur Mobilgeräte)
Dieses Dokument ist versionskontrolliert – schlagen Sie Änderungen auf GitHub vor.

