Controller name in data-action

In Stimulus 2.0 the controller name has been moved into the data-target attribute, however the data-action attribute remains the same.

<button
  data-my-controller-target="button"
  data-action="my-controller#expand"
></button>

Is there a reason data-action was not changed to make it consistent? This looks much nicer:

<button
  data-my-controller-target="button"
  data-my-controller-action="expand"
></button>
8 Likes

Great to see you posting on here, Ryan!

@marcoroth posted a similar issue on Github a little while ago.

I’ve got two guesses about issues with converting data-action off the top of my head. There could be more and they are all speculative/opinion:

  1. Targets get declared as static; informing the library what to look for. Thankfully, you don’t have to declare actions in a static array.
  2. It’s subjective, but I feel like a lot of folks use multiple actions on an element, which would lead to some truly long markup.
1 Like

Oh wow! It wasn’t on my mind to first check the the Discourse forum about “duplicates”.

Regarding the points @leastbad brought up:

  1. That’s right. Even though you don’t have to declare the actions in a static array you define the actions somehow statically by writing the actions in the controller :sweat_smile:
  2. I agree, but the same applies also for data-target. Either way, I think it should just be consistent overall. But I also tend to like the 1.1 syntax more.

The biggest problem I had in adopting Stimulus was naming conventions. After I got the first controller working, I’d move to the next one and it would not work! Because I screwed up the naming convention. I forgot to put the dot between the controller name and the target, or forget the controller js file name was camel cased, etc etc.

Right or wrong I started to camel case my controller name. My understanding about data- is that anything after data- is valid so
this worked (slim template):

div[data-controller="testMe"]
  = text_field_tag('from_date',nil,data:{target:'testMe.from_date', action:'change#doSomething'})

Because of my approach my conversion will be harder and I’m sure I’ll screw up some naming convention

div[data-controller="test-me"]
  = text_field_tag('from_date',nil,data:{'test-me-target':'from_date', action:'change#doSomething'})

Or a rails data form helper with symbol. I’ll also note that you can’t use camel case symbol as a data key (but you can in a regular hash)

div[data-controller="test-me"]
  = text_field_tag('from_date',nil,data:{test_me_target:'from_date', action:'change#doSomething'})

Wish everyone would get there Snakes, Camels and Kababs together:-)

P.S. Glad to see Ryan’s smiling face - I would of given up on Rails years ago if not for his efforts.

Hey, Ryan!

As of stimulus#149, actions are invoked in order for both consistency and to support “halting the chain”. Here’s a quick example to illustrate:

<button data-action="form#validate modal#expand"></button>

form#validate will always be invoked before modal#expand. If form#validate calls event.stopImmediatePropagation(), modal#expand won’t be invoked.

Changing to a scoped-by-controller-indentifier HTML syntax would make the ordering ambiguous and impossible to declare explicitly.


Here’s another way to think about the syntax changes in 2.0. Now, all of the properties you define as static … lines in your controllers follow the same data-[identifier]-* naming convention in your HTML:

// hello_controller.js
export default class extends Controller {
  static values = { name: String }
  static classes = [ "valid" ]
  static targets = [ "input" ]
  // …
}
<div
  data-controller="hello"
  data-hello-name-value="Ryan"
  data-hello-valid-class="input--valid">

  <input data-hello-target="input">
</div>
6 Likes

Thanks for the explanation Javan, that makes sense!

1 Like