Discourse 3.1.0.beta6 には、新しい <DModal> コンポーネントベースの API が搭載されています。
これは、現在非推奨となっている古いコントローラーベースの API を置き換えるものです。古い API を使用している既存のモーダルがある場合は、こちら here の移行ガイドをご覧ください。
モーダルのレンダリング
モーダルは、Handlebars テンプレートに <DModal> コンポーネントを含めることでレンダリングされます。適切なテンプレートをお持ちでない場合は、Using Plugin Outlet Connectors from a Theme or Plugin をご覧ください。
シンプルなモーダルは、以下のようなものになります。
<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}}
フッターの追加
多くのモーダルには、何らかの呼び出しアクション(Call-to-Action)が含まれています。Discourse では、これらは通常モーダルの下部に配置されます。これを実現するために、DModal にはコンテンツをレンダリングできる「名前付きブロック(named blocks)」がいくつか用意されています。以下は、フッターに 2 つのボタン(そのうち 1 つは標準的な 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。フォーカスがフォーム/テキストエリア/セレクトキット内でない限り、Enter キーで .d-modal__footer .btn-primary がクリックされます。 |
@beforeClose |
async ({ initiatedBy }) => boolean。close をキャンセルするには false を返します(例:未保存フォームの確認)。 |
@hidden |
キーボード処理を一時停止します。ネストされたモーダルが上にある場合に使用されます。 |
@tagName |
"div"(デフォルト)または "form"。ネイティブの送信が機能するようにフォームには "form" を使用してください。 |
ブロック
| ブロック | 位置 | 使用タイミング |
|---|---|---|
default / :body |
メインコンテンツエリア | デフォルトエリア |
:aboveHeader |
ヘッダーの直前、最上部 | 稀に必要。タイトルバーの上に配置する必要があるコンテンツ(例:バナー)用。 |
:headerAboveTitle |
ヘッダー内、タイトル前 | 存在するが未使用。稀に必要。 |
:belowModalTitle |
.d-modal__title 内、<h1> の後 |
補足的なメタ情報を入れるのに最適な位置。 |
:headerBelowTitle |
ヘッダー内、タイトルブロック後 | タブ、サブナビゲーション、またはヘッダーの一部である検索入力。 |
:headerPrimaryAction |
モバイルのみのヘッダー右側 | X 閉じるボタンをプライマリアクション(例:「保存」)に置き換えます。また、左側に「キャンセル」ボタンを自動レンダリングし、ヘッダーに .--has-primary-action を追加します。 |
:belowHeader |
ヘッダーとボディの間 | スクロール可能なボディの外側にある永続的なサブヘッダーコンテンツ(例:検索バー)。スクロールしても表示され続ける(sticky display)ように設定されます。 |
:aboveFooter |
ボディとフッターの間 | @hideFooter が設定されている場合は抑制されます。フッターに関連するがフッター外にあるコンテンツに使用します。これも稀です。 |
:footer |
下部アクションバー | プライマリおよびセカンダリボタン。ここにある最初の .btn-primary が Enter キーでトリガーされます。 |
:belowFooter |
フッター後 | 稀に必要。@hideFooter を無視します。枠線付きのフッターエリア外のステータステキストなどに有用。 |
出典:引数については インタラクティブなスタイルガイド、名前付きブロックについては d-modal テンプレートの実装 を参照してください。
CSS
コアを上書きするアンカーとして .d-modal クラスを使用し、レガシーな .modal セレクターは避けてください。
利用可能な 4 つの修飾子:
.--largeは 最大幅 を 800px に設定します(デスクトップのみ).--maxは 最大幅 を 90vw に設定します(デスクトップのみ).has-searchは 固定高さ(80vh)を設定します。結果の長さによる高さ変化を避けるために、検索/フィルタシステムを備えたモーダル用に設計されています(デスクトップのみ).--stackedはフッターのボタンをスタック表示に設定します(モバイルのみ)
このドキュメントはバージョン管理されています。変更を提案する場合は GitHub まで。

