この記事はGoogle翻訳の結果を編集したものです。
アクションはコントローラーでDOMイベントを処理する方法です。
<div data-controller="gallery">
<button data-action="click->gallery#next">…</button>
</div>
// controllers/gallery_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
next(event) {
// …
}
}
アクションは以下の間を接続します。
- コントローラーメソッド
- コントローラーの要素
- DOMイベントリスナー
記述子
data-action
値のclick->gallery#next
はアクション記述子と呼ばれます。この記述子では:
-
click
はリッスンするDOMイベントの名前です -
gallery
はコントローラーの識別子です -
next
は呼び出すメソッドの名前です
イベント速記
Stimulusを使用するとイベント名を省略して上記のボタン/クリックのペアなど、いくつかの一般的な要素/イベントのペアのアクション記述子を短縮できます。
<button data-action="gallery#next">…</button>
これらの短縮形のペアの完全なセットは次のとおりです。
要素 | デフォルトイベント |
---|---|
a | click |
button | click |
details | toggle |
form | submit |
input | input |
input type=submit | click |
select | change |
textarea | input |
キーボードイベントフィルター
特定のキーストロークが使用された場合にのみ、KeyboardEventアクションがコントローラーメソッドを呼び出す必要がある場合があります。
次の例のようにアクション記述子のイベント名に.esc
を追加することで、Escape
キーのみに応答するイベントリスナーをインストールできます。
<div data-controller="modal"
data-action="keydown.esc->modal#close" tabindex="0">
</div>
これは、発生するイベントがキーボードイベントである場合にのみ機能します。
これらのフィルターとキーの対応を以下に示します。
フィルター | キー |
---|---|
enter | Enter |
tab | Tab |
esc | Escape |
space | " " |
up | ArrowUp |
down | ArrowDown |
left | ArrowLeft |
right | ArrowRight |
home | Home |
end | End |
[a-z] | [a-z] |
[0-9] | [0-9] |
他のキーをサポートする必要がある場合、カスタムスキーマを使用して修飾子をカスタマイズできます。
import { Application, defaultSchema } from "@hotwired/stimulus"
const customSchema = {
...defaultSchema,
keyMappings: { ...defaultSchema.keyMappings, at: "@" },
}
const app = Application.start(document.documentElement, customSchema)
修飾キーを使用して複合フィルターにサブスクライブする場合はctrl+a
のように記述できます。
<div data-action="keydown.ctrl+a->listbox#selectAll" role="option" tabindex="0">...</div>
サポートされている修飾キーのリストを以下に示します。
修飾キー | 注釈 |
---|---|
alt |
MacOSのoption
|
ctrl |
|
meta |
MacOSのコマンドキー |
shift |
グローバルイベント
コントローラーはグローバルウィンドウまたはドキュメントオブジェクトでディスパッチされたイベントをリッスンする必要がある場合があります。
次の例のようにアクション記述子のイベント名に@window
または@document
を(任意のフィルター修飾子と共に)追加して、window
またはdocument
にそれぞれイベントリスナーをインストールできます。
<div data-controller="gallery"
data-action="resize@window->gallery#layout">
</div>
オプション
DOMイベントリスナーオプションを指定する必要がある場合、アクション記述子に1つ以上のアクションオプションを追加できます。
<div data-controller="gallery"
data-action="scroll->gallery#layout:!passive">
<img data-action="click->gallery#open:capture">
Stimulusは次のアクションオプションをサポートしています。
アクションオプション | DOMイベントリスナーオプション |
---|---|
:capture |
{ capture: true } |
:once |
{ once: true } |
:passive |
{ passive: true } |
:!passive |
{ passive: false } |
さらに、StimulusはDOMイベントリスナーオプションによってネイティブにサポートされていない次のアクションオプションもサポートしています。
カスタムアクションオプション | 説明 |
---|---|
:stop |
メソッドを呼び出す前にイベントで.stopPropagation() を呼び出します |
:prevent |
メソッドを呼び出す前にイベントで.preventDefault() を呼び出します |
:self |
イベントが要素自体によって発生した場合にのみメソッドを呼び出します |
Application.registerActionOption
メソッドを使用して独自のアクションオプションを登録できます。
たとえば<details>
要素がトグルされるたびにトグルイベントを送出するとします。カスタム:open
アクションオプションは要素がトグルされて開いたときにイベントをルーティングするのに役立ちます。
import { Application } from "@hotwired/stimulus"
const application = Application.start()
application.registerActionOption("open", ({ event }) => {
if (event.type == "toggle") {
return event.target.open == true
} else {
return true
}
})
同様にカスタム:!open
アクションオプションは要素が閉じられたときにイベントをルーティングできます。アクション記述子オプションを!で宣言するプレフィックスはコールバックでfalse
に設定された値引数を生成します。
import { Application } from "@hotwired/stimulus"
const application = Application.start()
application.registerActionOption("open", ({ event, value }) => {
if (event.type == "toggle") {
return event.target.open == value
} else {
return true
}
})
イベントがコントローラーアクションにルーティングされないようにするにはregisterActionOption
コールバック関数がfalse
を返す必要があります。 それ以外の場合、イベントをコントローラーアクションにルーティングするにはtrue
を返します。
コールバックは次のキーを持つ単一のオブジェクト引数を受け入れます。
| 名前 | 説明 |
| name | 文字列:オプションの名前(上記の例では"open"
) |
| value | 真偽値:オプションの値(:open
はtrue
を返し:!open
はfalse
を返します) |
| event | Event: イベントインスタンス |
| element | Element: アクション記述子が宣言されている要素 |
イベント オブジェクト
アクションメソッドはアクションのイベントリスナーとして機能するコントローラー内のメソッドです。
アクションメソッドの最初の引数はDOMイベントオブジェクトです。次のようなさまざまな理由でイベントへのアクセスが必要になる場合があります。
- キーボードイベントからキーコードを読み取る
- マウスイベントの座標を読み取る
- 入力イベントからデータを読み取る
- アクションサブミッター要素からパラメーターを読み取る
- イベントに対するブラウザのデフォルトの動作を防止する
- このアクションにバブルアップする前に、どの要素がイベントをディスパッチしたかを調べる
次の基本プロパティは、すべてのイベントに共通です。
イベントプロパティ | 値 |
---|---|
event.type | イベントの名前(例:"click" ) |
event.target | イベントをディスパッチしたターゲット(つまりクリックされた最も内側の要素) |
event.currentTarget | イベント リスナーがインストールされているターゲット(data-action 属性を持つ要素、またはdocument またはwindow のいずれか) |
event.params | アクションサブミッター要素によって渡されるアクションパラメーター |
次のイベントメソッドを使用するとイベントの処理方法をより詳細に制御できます。
イベントメソッド | 結果 |
---|---|
event.preventDefault() | イベントのデフォルトの動作をキャンセルします(リンクをたどる、フォームを送信するなど) |
event.stopPropagation() | 親要素の他のリスナーにバブルアップする前にイベントを停止します |
複数のアクション
data-action
属性の値はスペースで区切られたアクション記述子のリストです。
特定の要素に多くのアクションがあることはよくあることです。たとえば次の入力要素はフォーカスを取得するとフィールドコントローラーのhighlight()
メソッドを呼び出し、要素の値が変更されるたびにsearch
コントローラーのupdate()
メソッドを呼び出します。
<input type="text" data-action="focus->field#highlight input->search#update">
要素に同じイベントに対する複数のアクションがある場合、Stimulusは記述子が表示される順序で左から右にアクションを呼び出します。
アクション内でEvent#stopImmediatePropagation()
を呼び出すことにより、アクションチェーンをいつでも停止できます。右側への追加のアクションは無視されます。
highlight: function(event) {
event.stopImmediatePropagation()
// ...
}
命名規則
アクション名はコントローラーのメソッドに直接マップされるため、アクション名を指定する際は常にcamelCaseを使用してください。
click
、onClick
、handleClick
など単にイベントの名前を繰り返すアクション名は避けてください。
<button data-action="click->profile#click">Don't</button>
代わりに呼び出されたときに何が起こるかに基づいてアクションメソッドに名前を付けます。
<button data-action="click->profile#showDialog">Do</button>
これによりコントローラーのソースを見なくてもHTMLブロックの動作を理解することができます。
アクションパラメーター
アクションにはサブミッター要素から渡されるパラメーターを含めることができます。data-[identifier]-[param-name]-param
の形式に従います。パラメーターは渡される予定のアクションが宣言されているのと同じ要素で指定する必要があります。
すべてのパラメーターは値から推測されるNumber
、String
、Object
、またはBoolean
のいずれかに自動的に型キャストされます。
データ属性 | パラメーター | 型 |
---|---|---|
data-item-id-param="12345" |
12345 |
Number |
data-item-url-param="/votes" |
"/votes" |
String |
data-item-payload-param='{"value":"1234567"}' |
{ value: 1234567 } |
Object |
data-item-active-param="true" |
true |
Boolean |
次の設定を検討してください。
<div data-controller="item spinner">
<button data-action="item#upvote spinner#start"
data-item-id-param="12345"
data-item-url-param="/votes"
data-item-payload-param='{"value":"1234567"}'
data-item-active-param="true">…</button>
</div>
ItemController#upvote
とSpinnerController#start
の両方を呼び出しますが、パラメーターが渡されるのは前者だけです。
// ItemController
upvote(event) {
// { id: 12345, url: "/votes", active: true, payload: { value: 1234567 } }
console.log(event.params)
}
// SpinnerController
start(event) {
// {}
console.log(event.params)
}
イベントから他に何も必要ない場合はパラメーターを破棄できます。
upvote({ params }) {
// { id: 12345, url: "/votes", active: true, payload: { value: 1234567 } }
console.log(params)
}
または同じコントローラー上の複数のアクションが同じ送信者要素を共有する場合に備えて必要なパラメーターのみを破棄します。
upvote({ params: { id, url } }) {
console.log(id) // 12345
console.log(url) // "/votes"
}