HTMLCollections cannot be accessed with the `index` JSON Parser
https://github.com/elm-lang/core/blob/b06aa4421f9016c820576eb6a38174b6137fe052/src/Native/Json.js#L360-L372
Arrays are not the only thing which would respond to an index like call. HTMLCollection Objects can also be indexed. The code in lines 366- 371 will in fact work fine with an HTMLCollection (and its decedents).
Use Case:
Here we have a custom Event for the onsubmit event in a form which wishes to return the value of the first element of that form. Json.index 0 fails because target.elements is a HTMLFormControlsCollection and not an Array. The check on line 362 prevents this from succeeding, but there is no other reason to fail. As Json.Decode currently stands there is no way to decode anything within any kind of HTMLCollection.
import Json.Decode as Json
onSubmitWithIndex : Attribute String
onSubmitWithIndex =
onWithOptions
"submit"
{ defaultOptions | preventDefault = True }
(Json.at ["target", "elements"] <| Json.index 0 <| Json.field "value" <| Json.string)
-- N.B. This is a minimal example. Actual use cases are likely to be much more
-- nuanced abou how then dig into the elements object.
Possible Solutions:
- Include
HTMLCollectionalong with array on line 326:
if (!((value instanceof Array) || (value instanceof HTMLCollection)))
- Remove the check for array completely and us "duck typing" to determine if
valuecan be indexed. - Add a new combinator which allows arbitrary methods to be invoked on objects during JSON decoding.
- Add one or more new combinators specifically designed for the HTMLCollection interface.
Note that the same argument could be made for the array combinator beginning on line 235
Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!
Here is what to expect next, and if anyone wants to comment, keep these things in mind.
In case this is blocking anyone right now:
For a specific index
field (toString index) yourDecoder
For the whole collection
Decode the length field, then gather up the contents. This would work on a bunch of array-like structures.
https://ellie-app.com/jfWRHpCsga1/1
~I may add that (or something like it, perhaps with a better name) to elm-community/json-extra, as the question of how to do it comes up regularly.~
I've added this to elm-community/json-extra as collection
Normally I would expect folks to track inputs in their Model. That would mean that the submit button would not need to know anything about the particular text fields in any form. That'd be tracked elsewhere.
Why is this case different?
We have very big forms. And more often than not, we don't care about the form values until the form is submitted. The DOM is already quite good at tracking form contents and there is little value for us to track it, too.