Stimulus: Unifying action attributes

Created on 5 Dec 2020  Ā·  6Comments  Ā·  Source: hotwired/stimulus

Hey there, thanks for the new Stimulus 2.0 release!

I really love the new APIs!

After using the new unified target attributes introduced in #202 I asked myself why the same thing wasn't applied for the action attributes. Was there a specific reason to not do that?

The goal of unifying the target attributes was to align with the new values and classes APIs, so it would make sense to also adopt this syntax to the action attributes, right?

Personally I somehow dislike the new target attributes syntax, because it requires to write more HTML code. Especially if you have a lot of targets in your HTML markup - it seems to clutter up the HTML markup even more, which doesn't seem to be the goal of Stimulus. You end up with a lot of "new" data attributes on the element which are all named differently compared to one attribute which is always named data-target but can hold a bunch of targets.

<div data-controller="list sort">
  <div data-target="list.item sort.item">...</div>
</div>

Compared to:

<div data-controller="list sort">
  <div data-list-target="item" data-sort-target="item">...</div>
</div>

But I guess it just takes some time to get used to it.


Anyway, if we now take a look at the current action attributes it doesn't behave the same way.

Because the motivation for the target attribute change was to be consistent with the other APIs it would just make sense to also apply this "new" syntax on the action attributes.

Example:

<div data-controller="gallery">
  <button data-action="click->gallery#next">…</button>
</div>

becomes:

<div data-controller="gallery">
  <button data-gallery-action="click->next">…</button>
</div>

Or using the event shorthand syntax:

<button data-gallery-action="next">…</button>

Either way, I just think it would make sense to have a consistent API for all data attributesšŸ˜‰

I'm happy to discuss or to get to know the thought process behind that change!

Thank you!

Most helpful comment

There is a good reason why the actions are different: All actions are run from left to right and you ca cancel execution at any point, this would not be possible if all controllers had their own action attribute.

All 6 comments

Agreed about the new target syntax, seems to needlessly clutter HTML when you have a single element being used as target for multiple controllers, not to mention it is now impossible to simply find all elements that serve as target for any controller (searching for "data-target" in entire project).

Not to mention, it is a pain if you happen to use longer controller names for whatever reason. For example, we are using BEM-like naming convention for our classes and controllers ("form_contact_call" for example), which would now be rather problematic to write (data-form-contact-call-target, I guess?)

I get the desire to have data attribute syntax unified, but If anything, I would like to see the support for "legacy" be kept alive even in future version.

I dislike the syntax too, data-target was way better markup in the code, you instantly knew where do you have your targets, actions and controllers. I get why the syntax is necessary with the values and classes api, but it seems unnecessary for targets.

Also this is really breaking change and I really don't like removing the legacy support in future versions.
If unifying is the reason, I would rather go the other way. Use the old syntax and do something like this:

data-class="search.loading#search--busy"
data-values="loader.url#'/messages'"

And to be honest I always disliked the reverse syntax in javascript too. I'm rather using this kind of syntax for my projects this.target.results than this.resultsTarget. It has it's pros and cons. Pros is that it's much easier to read and this syntax is more friendly for IDEs. Cons is that you have to define the targets with longer syntax.

    get target() {
        return {
            results: this.targets.find("results")
        }
    }

And please don't apply this new syntax also on action attributes, that would really destroy the easy convenient HTML markup that stimulus always had. I think data-controller, data-controller, data-action, data-target was always so simple, that's why I liked stimulus in the first place. And adding data-class, data-values to that would be much better way to go, for me the new syntax is step back.

I agree with both of you @Eldzej @evromalarkey.
I'd also love to keep the old markup, or at least that both of them still continue to work (after V2) without favoring one over the other. Deprecating the old syntax would be a step back.

But if we are just going to see the new syntax being supported going forward it should at least be consistent in my opinion.

There is a good reason why the actions are different: All actions are run from left to right and you ca cancel execution at any point, this would not be possible if all controllers had their own action attribute.

Cross-posting the explanation I just shared at https://discourse.stimulusjs.org/t/controller-name-in-data-action/1499/5 and closing for now. Thanks for the feedback.

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" ]
  // …
}

```html

```

Was this page helpful?
0 / 5 - 0 ratings