core icon indicating copy to clipboard operation
core copied to clipboard

HTMLCollections cannot be accessed with the `index` JSON Parser

Open antarestrader opened this issue 8 years ago • 4 comments

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 HTMLCollection along 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 value can 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

antarestrader avatar Oct 06 '17 15:10 antarestrader

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.

process-bot avatar Oct 06 '17 15:10 process-bot

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

zwilias avatar Oct 07 '17 12:10 zwilias

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?

evancz avatar Oct 08 '17 17:10 evancz

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.

muelli avatar Sep 08 '18 21:09 muelli