Can we bring the HTML tag attributes behaviour to the next level?


I always wondered why the inputs for attributes in rails tags are so limited. I just ran across this again while using Hotwired. The tag helper methods are documented here: TagHeper

First, here is an example to work with, ignoring what Turbo actually does. It’s all about how it converts data attributes into HTML.

helper.tag.div nil, data: {turbo_action: "click->controller#action hover->controller#action"}
# => "<div data-turbo-action=\"click-&gt;controller#action\"></div>"
#                    ^ notice how the _ in turbo_action was converted to a -

I would like to be able to write the above example in all of these ways, while having the same html. Of course that would require some sane defaults.

helper.tag.div nil, data: {turbo: {action: "click->controller#action hover->controller#action"}}
# => "<div data-turbo=\"{&quot;action&quot;:&quot;click-\\u003econtroller#action hover-\\u003econtroller#action&quot;}\"></div>"
#                       ^ notice how we get a hash. I assume it calls .to_s
helper.tag.div nil, data: {turbo: {action: ["click->controller#action", "hover->controller#action"]}}
# => "<div data-turbo=\"{&quot;action&quot;:[&quot;click-\\u003econtroller#action&quot;,&quot;hover-\\u003econtroller#action&quot;]}\"></div>"
#                                                                                     ^ wouldn't it be nice if it joined the array with spaces?                                         
helper.tag.div nil, data: {turbo_action: ["click->controller#action", "hover->controller#action"]}
# => "<div data-turbo-action=\"[&quot;click-\\u003econtroller#action&quot;,&quot;hover-\\u003econtroller#action&quot;]\"></div>"
#                                                                         ^ same here, I would prefer if it joined with spaces

To take this even further. We can assume different behaviour for different attributes types. For example for style we should write it in to css.

helper.tag.div nil, style: "color: green;"
# => "<div style=\"color: green;\"></div>"
helper.tag.div nil, style: {color: :green}
# => "<div style=\"color green\"></div>"
#                       ^ why isn't it color: green;

# This would enable us to do stuff like this:
BASE_STYLE = {color: :green, padding: "4px"}
helper.tag.div nil, style: BASE_STYLE.merge(color: "red !important")
# => "<div style=\"color red !important padding 4px\"></div>"
#                       ^:             ^;      ^:  ^;

# And this
helper.tag.div nil, style: {color: :green, border: ["1px", :solid, :black]}
# => "<div style=\"color green border [&quot;1px&quot;, :solid, :black]\"></div>"
#                       ^:    ^;     ^:                           ^;

For javascript: we could add semicolons;

helper.tag.div nil, onclick: "one(); two():"
# => "<div onclick=\"one(); two():\"></div>"
helper.tag.div nil, onclick: ["one()", "two():"]
# => "<div onclick=\"one() two():\"></div>"
#                         ^ why isn't there a ; or && or ||
helper.tag.div nil, onclick: {one: "one()", two: "two():"} # I have no idea what should happen here.

It also just discovered that we already have a precedent for such a behaviour. This happens when using the class attribute:

helper.tag.div nil, class: "green padding"
# => "<div class=\"green padding\"></div>"
helper.tag.div nil, class: ["green", :padding]
# => "<div class=\"green padding\"></div>"
#                       ^ it did the right thing, no comma, no symbols or arrays

I assume we could define a better conversion for these attributes, and maybe more:

  • data
  • class
  • for all js events; onclick, onmouseover, …
  • href
  • id
  • title
  • alt

What’s your opinion?


IMHO, too many options lead to:

  1. Longer decision times
  2. Potentially inconsistent code
  3. Much more useless work for the rails team
  • vlad
1 Like