Techioz Blog

Stimulus を使用して複数のアクションを同じイベントにバインドする

概要

Rails テンプレートの Stimulus を使用して複数のアクションを同じイベントにバインドできるかどうかを知っている人はいますか?

私は現在これを持っています:

<%= form.text_area :content, value: '', id: "message-input",
                           data: { action: "input->message-form#inputChange input->form#autogrowInput 
                           keydown.enter->message-form#sendMessage keydown.enter->message-actions#clearReply 
                           keydown.ctrl+enter->message-form#addNewLine keydown.ctrl+enter->form#autogrowInput", message_form_target: "messageInput", form_target: "inputField" },
                           class: "form-input-no-label", autofocus: true %>

イベント呼び出しの重複を避け、次のように複数のアクションを連鎖させたいと考えています。

<%= form.text_area :content, value: '', id: "message-input",
                           data: { action: "input->message-form#inputChange form#autogrowInput
                           keydown.enter->message-form#sendMessage message-actions#clearReply
                           keydown.ctrl+enter->message-form#addNewLine form#autogrowInput", message_form_target: "messageInput", form_target: "inputField" },
                           class: "form-input-no-label", autofocus: true %>

ただし、これにより、指定されたアクションが機能しなくなります。

イベントの重複を回避できるかどうか知っている人はいますか?

解決策

コードをフォーマットするだけの方がよいでしょう。

<%= form.text_area :content,
  data: {
    action: %(
      input->message-form#inputChange
      input->form#autogrowInput
      keydown.enter->message-form#sendMessage
      keydown.enter->message-actions#clearReply
      keydown.ctrl+enter->message-form#addNewLine
      keydown.ctrl+enter->form#autogrowInput
    ),
    message_form_target: :messageInput,
    form_target: :inputField
  }
%>

こうすることで、行をすばやくコピーして貼り付けたり、移動したりすることができます。

あるいは、ヘルパーを作成することもできます。

# app/helpers/application_helper.rb

def data_action hash
  hash.map do |event, actions|
    actions.map do |controller, action|
      "#{event}->#{controller.to_s.dasherize}##{action}"
    end
  end.join(" ")
end
<%= form.text_area :content,
  data: {
    action: data_action(
      input:                {message_form: :inputChange, form: :autogrowInput},
      "keydown.enter":      {message_form: :sendMessage, message_actions: :clearReply},
      "keydown.ctrl+enter": {message_form: :addNewLine,  form: :autogrowInput}
    ),
    message_form_target: :messageInput,
    form_target: :inputField
  }
%>