Discourse 3.1.0.beta6 发布了一个全新的基于组件的 <DModal> API。
此 API 已取代旧的基于控制器的 API,后者现已废弃。如果您有使用旧 API 的现有模态框,请查看此处的迁移指南。
渲染模态框
通过在 Handlebars 模板中包含 <DModal> 组件来渲染模态框。如果您还没有合适的模板,请查看 https://meta.discourse.org/t/using-plugin-outlet-connectors-from-a-theme-or-plugin/32727。
一个简单的模态框示例如下:
<DButton
@translatedLabel="显示模态框"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<DModal @title="我的模态框" @closeModal={{fn (mut this.modalIsVisible) false}}>
你好,世界,这是模态框中的一些内容
</DModal>
{{/if}}
此处使用了
mut辅助函数 作为一种仅适用于 hbs 的赋值方式。您也可以通过任何其他标准的 Ember 方法来设置modalIsVisible。
此示例将创建一个简单的模态框,如下所示:
封装为组件
在引入更多复杂性之前,通常最好将新的模态框封装在其自己的组件定义中。让我们将 <DModal> 相关内容移动到一个新的 <MyModal /> 组件中:
// components/my-modal.gjs
<template>
<DModal @title="我的模态框" @closeModal={{@closeModal}}>
你好,世界,这是模态框中的一些内容
</DModal>
</template>
将此 .gjs 文件升级为基于类的组件,将允许您引入更复杂的逻辑和状态。
要使用新组件,请更新调用位置以引用它,并确保传入 @closeModal 参数。
<DButton
@translatedLabel="显示模态框"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}
添加页脚
许多模态框都包含某种行动号召。在 Discourse 中,这些通常位于模态框底部。为实现这一点,DModal 提供了一些“命名块”,可以在其中渲染内容。以下是更新后的示例,其中包含两个页脚按钮,其中一个是标准的 DModalCancel 按钮:
<DModal @title="我的模态框" @closeModal={{@closeModal}}>
<:body>
你好,世界,这是模态框中的一些内容
</:body>
<:footer>
<DButton class="btn-primary" @translatedLabel="提交" />
<DModalCancel @close={{@closeModal}} />
</:footer>
</DModal>
从非 hbs 上下文中渲染模态框
理想情况下,<DModal> 实例应使用上述声明式技术在 Ember 模板中渲染。如果您的用例无法实现这一点,可以通过注入 modal 服务并调用 modal.show() 来完成。
请确保已按照上述说明将模态框封装在其自己的组件中。然后,通过将组件类的引用传递给 showModal 来触发模态框:
import MyModal from "discourse/components/my-modal";
// (在相关位置注入 modal 服务)
// 每当需要打开模态框时,添加此调用。
// `@closeModal` 参数将自动传递给您的组件。
this.modal.show(MyModal);
// 可选地,传递一个 `model` 参数。该参数将作为 `@model` 传递给您的组件。
// 它可以包含数据,也可以包含模态框要使用的操作/回调。
this.modal.show(MyModal, {
model: { topic: this.topic, someAction: this.someAction },
});
// `modal.show()` 返回一个 Promise,因此您可以等待它关闭
// 它将以传递给 `@closeModal` 操作的数据进行解析
const result = await this.modal.show(MyModal);
更多自定义选项!
<DModal> 具有多个命名块和参数。
参数
| 参数 | 目的 |
|---|---|
@closeModal |
必需,否则不会显示关闭 UI。 |
@title |
渲染 <h1 id="discourse-modal-title">;绑定 aria-labelledby。 |
@subtitle |
标题下方的小字。 |
@flash / @flashType |
模态框顶部的内联警报(DFlashMessage)。 |
@hideHeader, @hideFooter |
隐藏整个区域。 |
@headerClass, @bodyClass |
标题/主体包装器的额外类。 |
@dismissable |
当设置 @closeModal 时默认为 true。禁用 Esc / 背景点击 / X。 |
@autofocus |
默认为 true。通过 dTrapTab 自动聚焦第一个可聚焦元素。 |
@submitOnEnter |
默认为 true。除非焦点在表单/文本区域/select-kit 中,否则 Enter 键会点击 .d-modal__footer .btn-primary。 |
@beforeClose |
async ({ initiatedBy }) => boolean。返回 false 以取消关闭(例如脏表单确认)。 |
@hidden |
暂停键盘处理;当有嵌套模态框在最上层时使用。 |
@tagName |
"div"(默认)或 "form"。对于表单请使用 "form",以便原生提交功能生效。 |
块
| 块 | 位置 | 使用场景 |
|---|---|---|
default / :body |
主内容区域 | 默认区域 |
:aboveHeader |
最顶部,标题栏之前 | 很少需要;用于必须位于标题栏上方的内容(例如横幅)。 |
:headerAboveTitle |
标题栏内部,标题之前 | 存在但未使用。很少需要。 |
:belowModalTitle |
在 .d-modal__title 内部,<h1> 之后 |
补充元信息的绝佳位置。 |
:headerBelowTitle |
标题栏内部,标题块之后 | 标签、子导航或属于标题栏的搜索输入。 |
:headerPrimaryAction |
仅在移动设备上位于标题右侧 | 用主要操作(例如“保存”)替换 X 关闭按钮。还会在左侧自动渲染“取消”按钮,并为标题添加 .--has-primary-action。 |
:belowHeader |
标题栏和主体之间 | 持久性子标题内容(例如搜索栏),位于可滚动主体之外,因此具有固定显示效果。 |
:aboveFooter |
主体和页脚之间 | 当设置 @hideFooter 时会被抑制。用于与页脚关联但位于其外的内容。也很少使用。 |
:footer |
底部操作栏 | 主要和次要按钮。此处的第一个 .btn-primary 是 Enter 键触发的目标。 |
:belowFooter |
页脚之后 | 很少需要;忽略 @hideFooter。适用于边框页脚区域外的状态文本。 |
来源:交互式风格指南(用于参数),以及 d-modal 模板实现(用于命名块)。
CSS
使用 .d-modal 类作为锚点来覆盖核心样式,并避免使用遗留的 .modal 选择器。
可用 4 个修饰符:
.--large将最大宽度设置为 800px(仅限桌面).--max将最大宽度设置为 90vw(仅限桌面).has-search设置固定高度(80vh):适用于带有搜索/过滤系统的模态框,以避免根据结果长度改变高度(仅限桌面).--stacked将页脚按钮设置为堆叠布局(仅限移动设备)
本文档已进行版本控制——请在 GitHub 上提出更改建议。

