-
Notifications
You must be signed in to change notification settings - Fork 98
Use attributes instead of properties #259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
downloadAs : String -> Attribute msg | ||
downloadAs = | ||
stringProperty "download" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was unused (not exposed).
value string = | ||
-- Note: `.value` has no corresponding attribute, so we have to set it | ||
-- using a property. It can also be modified by the user by typing in inputs. | ||
-- Properties are diffed against the actual DOM, not the virtual DOM, so | ||
-- this ensures that the DOM is up-to-date with the model. | ||
Elm.Kernel.VirtualDom.property "value" (Json.string string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value
is an exception where we have to use a property, not an attribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Properties are diffed against the actual DOM, not the virtual DOM, so this ensures that the DOM is up-to-date with the model.
This refers to the implementation in elm/virtual-dom#187
2. When initializing an Elm app, you give it a DOM node to render into, or the `<body>` node is used. What happens if the node to render into isn’t empty? Elm then _virtualizes_ the DOM into virtual DOM. If the DOM nodes match what your app’s first render, the virtual DOM diffing won’t find any changes to make. This allows for server side rendering HTML, and then have Elm take over that content and avoiding lots of work at startup. Let’s take `<a href="/about">` as an example again. When virtualizing, Elm has to make a guess: Did you use `property "href" (Json.Encode.string "/about")` or `attribute "href" "/about"` in your Elm code? If we guess wrong, the first render will do an unnecessary DOM update, and if we guess right the first render won’t do anything as expected. Another complication is that attributes and properties don’t always have the same name, as mentioned above. When virtualizing DOM nodes, it’s possible to loop over all _attributes_ that are set, but it’s not possible to loop over properties. For `<div class="user-info">`, a loop over attributes would get that `class` attribute, but if `Html.Attributes.class` is implemented with a property, we would have to translate `class` into `className` with a lookup table. By primarily using attributes in `Html.Attributes`, we don’t need a lookup table (except for a couple of edge cases). | ||
|
||
3. Some properties are read only – if you try to assign them an error is thrown. The most notable example of this is trying to do `.className = "my-class"` on an SVG element. That throws an error, while `.setAttribute("class", "my-class")` works. In Elm, both `Html msg` and `Svg msg` are type aliases for the same virtual DOM node type, so you can mix functions from elm/html and elm/svg without getting type errors. `Html.Attributes.class` used to be implemented by setting the `className` property, and a common mistake was accidentally using using `Html.Attributes.class` on an SVG element, instead of `Svg.Attributes.class` (which is implemented by setting the `class` attribute), which would then cause hard to debug runtime errors. By setting the `class` attribute in `Html.Attributes.class` this issue is avoided. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related: elm/svg#24 is not really needed anymore, since Html.Attributes.classList
now works on SVG too.
Intro
This PR is a companion to elm/virtual-dom#187. That elm/virtual-dom PR works without this elm/html PR, but virtualization won’t work 100 % without it.
This PR removes the
stringProperty
helper function, and uses attributes for the exposed functions that used it instead. TheboolProperty
function is kept, and I added a comment for why.Details
Most functions in
Html.Attributes
that take aString
used this helper function:For example,
href
:In other words, lots of the
Html.Attributes
functions were implemented by setting properties.This PR removes
stringProperty
, and instead prefers attributes over properties. Here’shref
in this PR:In short, attributes are preferred because:
Html.Attributes
functions are attributes. Closes elm/virtual-dom#144I explain those points more in the
properties-vs-attributes.md
file (which I updated in this PR).