DModal API を使用して Discourse でモーダルウィンドウ(ポップアップ/ダイアログ)をレンダリングする

Discourse 3.1.0.beta6 には、新しい <DModal> コンポーネントベースの API が搭載されています。

:information_source: これは、現在非推奨となっている古いコントローラーベースの API に取って代わるものです。既存の古い API を使用しているモーダルがある場合は、こちら の移行ガイドをご覧ください。

モーダルのレンダリング

モーダルは、ハンドルバーステンプレートに <DModal> コンポーネントを含めることでレンダリングされます。適切なテンプレートをお持ちでない場合は、Using Plugin Outlet Connectors from a Theme or Plugin をご覧ください。

シンプルなモーダルは、以下のようなものになります。

<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.gjs
<template>
  <DModal @title="My Modal" @closeModal={{@closeModal}}>
    Hello world, this is some content in a modal
  </DModal>
</template>

この .gjs ファイルをクラスベースのコンポーネントにアップグレードすることで、より複雑なロジックや状態を導入できるようになります。

新しいコンポーネントを使用するには、呼び出し元を更新して参照し、@closeModal 引数を渡すようにしてください。

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

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

フッターの追加

多くのモーダルには、何らかの呼び出しアクション(コール・トゥ・アクション)が含まれています。Discourse では、これらは通常モーダルの下部に配置されます。これを実現するために、DModal にはコンテンツをレンダリングできる複数の「名前付きブロック」が用意されています。以下は、フッターに 2 つのボタン(そのうち 1 つは標準的な 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 テンプレート内でレンダリングされるべきです。ユースケースによってはそれが現実的でない場合、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 で提案してください。

「いいね!」 17

投稿が新しいトピックに分割されました: head_tagからモーダルを表示できますか