使用 DModal API 在 Discourse 中渲染 Modal 窗口(亦称弹窗/对话框)

Discourse 3.1.0.beta6 引入了一个全新的基于 <DModal> 组件的 API。

:information_source: 这取代了旧的基于控制器的 API,该 API 现在已弃用。如果您有使用旧 API 的现有模态框,请在此处查看迁移指南:https://meta.discourse.org/t/converting-modals-from-legacy-controllers-to-new-dmodal-component-api/268057

渲染模态框

模态框通过在 handlebars 模板中包含 <DModal> 组件来渲染。如果您还没有合适的模板,请查看 https://meta.discourse.org/t/using-plugin-outlet-connectors-from-a-theme-or-plugin/32727

一个简单的模态框看起来像这样:

<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}}

:information_source: mut 助手 在这里用作仅 hbs 的方式来设置值。您也可以使用任何其他标准的 Ember 方法来设置 modalIsVisible

此示例将创建一个简单的模态框,如下所示:

封装在组件中

在引入更多复杂性之前,通常最好将新的模态框封装在其自己的组件定义中。让我们将 <DModal> 内容移到一个新的 <MyModal /> 组件中。

{{! components/my-modal.hbs }}
<DModal @title="My Modal" @closeModal={{@closeModal}}>
  Hello world, this is some content in a modal
</DModal>

引入一个配套的 .js 组件文件将允许您引入更复杂的逻辑和状态。

要使用新组件,请更新调用站点以引用它,确保传递 @closeModal 参数。

<DButton
  @translatedLabel="Show Modal"
  @action={{fn (mut this.modalIsVisible) true}}
/>

{{#if this.modalIsVisible}}
  <MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}

添加页脚

许多模态框都有某种行动号召。在 Discourse 中,这些通常位于模态框的底部。为了实现这一点,DModal 有许多“命名块”,可以在其中渲染内容。以下示例已更新,以在页脚中包含两个按钮,其中一个是标准的 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>

从非 hbs 上下文渲染模态框

理想情况下,<DModal> 实例应该使用上面演示的声明式技术从 Ember handlebars 模板中渲染。如果这不适用于您的用例(例如,您需要从 Discourse 的旧“raw-hbs”或“widget”渲染系统触发模态框),则可以通过注入 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> 具有许多命名块和参数。请查看交互式样式指南以了解参数,以及d-modal 模板实现以了解命名块。


本文档是版本控制的 - 请在 github 上提出更改建议:https://github.com/discourse/discourse-developer-docs/blob/main/docs/03-code-internals/11-dmodal-api.md

17 个赞

帖子已拆分为新主题:Can I show a modal from head_tag