The `.value` is a lie.🎂 (on viewof'ed inputs at least)

Hey folks,
According to https://observablehq.com/@observablehq/introduction-to-views
these two snippets should be equivalent.

box // true
(box, viewof box.value) // "on"

given that

viewof box = html`<input type="checkbox" checked>`

However the latter returns the value attribute of the dom node, which is “on” by default.

So what kind of magic is actually happening under the hood?
Is Observable just treating inputs differently and using value for everything else?

Resetting the value and firing an input event doesn’t actually change the value propagated to the cells depending on it, probably because it’s fired on the input cell, and not on the stdlib Generators.input object.

Is it possible to access that object directly? Should Generators.input register an input event listener on it’s wrapped value? Thoughts?

1 Like

Think of viewof as a macro that produces an additional Runtime Variable (internal represenation of a cell) for your viewof cell, so that you end up with two Variables:

  • viewof box, the cell that you originally defined,
  • box, which is a generator cell that listens to changes in viewof box via Generators.input and yields the new value.

Generators.input has some “magic” for inputs. Depending on the input type, it will:

  • listen to different events (e.g. “click” for checkboxes),
  • cast the value (e.g. via .valueAsNumber() for number and range inputs).

You can find the implementation details here:

In general I find that looking at a notebook’s generated source can give some insight into the underlying logic, e.g.:
https://api.observablehq.com/@observablehq/introduction-to-views.js?v=3

2 Likes

Hey @mootari,
Yeah, so the .value is just the default case.
However then I’d actually argue that Generators.input has a bug, in that it should also listen for “input” events.
Yes one could emit a ‘clicked’ event for checkboxes e.t.c. but that feels like a weird API violation, no? I mean ideally instead of using ‘value’ observable would probably use a Symbol('value')
to prevent data transparency issues, but I guess that’s too late now :smiley:.

Btw, while I got you on the figurative phone, there’s a small bug in Mutable Forms / Fabian Iwand / Observable where it breaks for checkbox with just a single value. I haven’t tracked down the bug far enough, but it looks like browsers automatically wrap multiple checkboxes in a RadioNodeList but leave single checkboxes as is.
Yay auto unwrapping -.- .

1 Like

That would cause the generator to yield multiple times for a single update. If you want to investigate and visualize the events, have a look at https://observablehq.com/@mootari/monitoring-events.

As far as I recall there are some problems with input events on checkbox elements, specifically that the checked state will still have the old state when the event is raised. However, you can work around the issue by wrapping your element in a span or div and either have the input event bubble, or trigger it directly on the wrapper.

Thanks, fixed!

1 Like

Ah yeah you’re right.
Normally I really appreciate observables “nothing in-between” approach, but I think in this case it would have been fine to add a bunch of shim methods to input elements the moment they are passed to Observers.input, which abstract away the different behaviours and package them into one neat “input” event and Symbol(value) attribute.

Anyways, thanks for the help, and the fix! :smiley: