In the html -vs- only in the DOM

I’m an Elm newbie happily working my way through Elm in Action by Richard Feldman
(Code below is, I think, © 2017 Manning Publications. No infringement intended.)

Following a ‘Tip’ suggestion to improve the code (Section 3.2.4) I added a checked attribute to a radio button input so that the buttons correctly represent the model’s initial state on page load. And it works.

However, when I use Chromium’s inspector, my radio inputs all look like this:
<input type="radio" name="size">
None of them, including the one generated with checked True, have a checked attribute.

My question is:
What determines which attributes (and tags?) appear in the viewable page elements, and which will only exist in the DOM? Or am I misinterpreting what’s happening?


The (relevant) code:

...
viewSizeChooser : ThumbnailSize -> Html Msg
viewSizeChooser size =
  label []
    [ input [ type_ "radio", name "size", checked (isDefaultSize size), onClick (SetSize size) ] []
    , text (sizeToString size)
    ]

isDefaultSize : ThumbnailSize -> Bool
isDefaultSize size =
  size == initialModel.chosenSize
...

Inspector output:

...
<div id="choose-size">
  <label>
    <input type="radio" name="size">
    small
  </label>
  <label>
    <input type="radio" name="size">
    medium
  </label>
  <label>
    <input type="radio" name="size">
    large
  </label>
</div>
...

You’ve encountered one of those confusing parts of the HTML/DOM specification: the subtle differences between the properties and attributes of a node.

HTML/DOM

Roughly speaking, attributes are values that are set using the regular HTML attribute syntax checked ="checked" on a tag. Some (all?) of these are eventually converted into internal properties on the DOM node. Some (all?) properties can also be set directly using JavaScript like myNode.checked = true.

This means some values can be set via both attributes or properties but the resulting behavior can be slightly different depending on how it’s set :cold_sweat:

If you want to dig into the topic more, check out this Stack Overflow thread and this article.

Elm

All this brings us to Elm. All the functions in Html.Attributes are built on top of either Html.Attributes.attribute or Html.Attributes.property allowing attributes and properties respectively to be set.

In particular, Html.Attributes.checked is built in terms of property which has the effect of not showing checked="checked" when you inspect the DOM. If you implemented it in terms of attribute then it would show up:

input [type_ "radio", attribute "checked" "checked"] []

Here’s an Ellie example of building checked inputs with the checked helper, directly with attribute and directly with property. Run it and inspect the DOM for each of those to get a feel for the difference :smiley:

Finally, this distinction is tricky enough that elm-lang/html has a document on the differences.

9 Likes

Super clear and helpful response Joel!

2 Likes

@joelq Brilliant! Thank you. Great explanation and references, and even an example :slight_smile:

1 Like