# Transitive synchronized inputs

**URL:** <https://talk.observablehq.com/t/transitive-synchronized-inputs/8597>\
**Category:** Help\
**Created:** [December 12, 2023, 7:53pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597 "2023-12-12T19:53:51Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![jmatsushita](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jmatsushita/32/8324_2.png) [@jmatsushita](https://talk.observablehq.com/u/jmatsushita)\
**Post date:** [December 12, 2023, 7:53pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/1 "2023-12-12T19:53:51Z")

</div>

Hello hello,

First time poster here. I have the following question and a [notebook that shows an unexpected behavior I’m trying to understand](https://observablehq.com/@jmatsushita/transitive-reactive-input-dependencies):

### Setup

- Create three inputs source, middle, target
- Bind source to middle `Inputs.bind(viewof middle, viewof source)`
- Bind middle to target `Inputs.bind(viewof target, viewof middle)`

### Expected

- typing in any input updates the two other inputs.

### Actual

- typing in source updates only middle
- typing in middle or target updates the two other inputs.

It’s unexpected that binding inputs is not transitive… Maybe I’m doing something wrong.

> I understand I could bind target to source also but I thought this would work so I’m trying to figure out why it’s not 🙂

Cheers,

Jun

---

<div class="post-metadata">

**Author:** ![mootari](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mootari/32/581_2.png) [@mootari](https://talk.observablehq.com/u/mootari)\
**Post date:** [December 12, 2023, 11:05pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/2 "2023-12-12T23:05:49Z")

</div>

Think of `Inputs.bind()` as adding remote controls for your primary input. [To quote the docs](https://github.com/observablehq/inputs#inputsbindtarget-source-invalidation):

> The relationship between _target_ and _source_ is not symmetric: the _target_ input should be considered a dependant of the _source_ input, and if desired, only the _source_ should be declared an Observable view.

---

<div class="post-metadata">

**Author:** ![jmatsushita](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jmatsushita/32/8324_2.png) [@jmatsushita](https://talk.observablehq.com/u/jmatsushita)\
**Post date:** [December 13, 2023, 9:44am UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/3 "2023-12-13T09:44:14Z")

</div>

Hi @mootari

Thanks for your answer. I understand the relationships are not symmetric, my question is why are they not transitive?

In the notebook example the primary input and dependency relationships set up are:

- `Inputs.bind(viewof middle, viewof source)`
  - Primary input is `source`, i.e. `midde` is a dependent of `source`
  - So events flow `source -> middle`

- `Inputs.bind(viewof target, viewof middle)`
  - Primary input is `middle`: i.e. `target` is a dependent of `middle`
  - So events fow `middle -> target`

If that’s the case, my question is, why don’t event flow from `source -> target`. i.e. why is the `bind` relationship not transitive?

Hope this clarify my question!

Jun

---

<div class="post-metadata">

**Author:** ![jmatsushita](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jmatsushita/32/8324_2.png) [@jmatsushita](https://talk.observablehq.com/u/jmatsushita)\
**Post date:** [December 13, 2023, 2:18pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/4 "2023-12-13T14:18:31Z")

</div>

I realise I can ask my question with a more practical angle:

- How can I make it so, that when typing in `source` I see both `middle` and `target` update their content?
- How come `bind`ing `source -> middle` and `middle -> target` doesn’t work for that purpose?

---

<div class="post-metadata">

**Author:** ![tomlarkworthy](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/tomlarkworthy/32/5940_2.png) [@tomlarkworthy](https://talk.observablehq.com/u/tomlarkworthy)\
**Post date:** [December 13, 2023, 9:15pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/5 "2023-12-13T21:15:38Z")

</div>

Use Inputs.input() as a fake source.

Bind the real UI inputs to that one.

there is a diagram here [Scaling User Interface Development / Tom Larkworthy | Observable](https://observablehq.com/@tomlarkworthy/ui-development#controlling_views)

---

<div class="post-metadata">

**Author:** ![mootari](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mootari/32/581_2.png) [@mootari](https://talk.observablehq.com/u/mootari)\
**Post date:** [December 14, 2023, 12:40am UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/6 "2023-12-14T00:40:09Z")

</div>

As mentioned in the excerpt I shared above, you should only have _one_ viewof cell:

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/5/5b71606563280e201acdfe8d3e30bf4110e2f490.png)

As for why it doesn’t work transitively in both directions: Inputs.bind only dispatches `input` events on the _source_ ([see implementation](https://github.com/observablehq/inputs/blob/130d8cf30d12256ac89cee518be08469105ed300/src/bind.js#L7)). The input event is required to let Observable’s Runtime know that a viewof cell’s _value_ has changed and that dependent cells should be invalidated and rerun with the updated value. Programmatically setting a form element’s value however does not automatically dispatch an event.

So while typing in `target` will dispatch on `middle` which in turn will dispatch on `source`, the same isn’t true for the other direction because `Inputs.bind()` relies on these events to know when to update bound inputs.

---

<div class="post-metadata">

**Author:** ![jmatsushita](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jmatsushita/32/8324_2.png) [@jmatsushita](https://talk.observablehq.com/u/jmatsushita)\
**Post date:** [December 14, 2023, 12:09pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/7 "2023-12-14T12:09:46Z")

</div>

@tomlarkworthy Great seeing you here, and thanks for sharing your write up! It really goes in depth and helps a lot. Composability is what indeed I was trying to achieve, and it so happens that my intended use case and what I’m trying to troubleshoot involves your `localStorageView` component! What happened is that I was trying to use `@cmudig/editor` but was having trouble wiring it with `localStorageView` and another button input in this notebook `@jmatsushita/try-purescript` (sorry as a new user I only have a budget for 2 links 😕 )

I suggested the following changes to `@cmudig/editor` to try and make the editor reusable (which have been merged since)

```auto
// support sending and receiving updates as per https://observablehq.com/@tophtucker/custom-input-example
  Object.defineProperty(container, "value", {
    get() {
      // console.log("editor.get called:", ed.textContent)
      return ed.textContent;
    },
    set(v) {
      // console.log("editor.set called with: ",v)
      ed.textContent = v;
      jar.updateCode(v);
    }
  });

```

And added a couple of use cases that were not supported before:

- Setting the value programmatically
- Supporting persistence with localStorageView

However when trying to wire both of these use cases in `@jmatsushita/try-purescript` I was scratching my head and started this thread.

I tried your suggestion to create a fake source with `Inputs.input()`, but It didn’t work, I think because then the binding direction with the localStorageView wasn’t right. Which led to errors

```auto
Uncaught TypeError: e.closest is not a function
    at inputs.min.js:40:1444

```

I created a [miminal reproducer here](https://observablehq.com/d/f7e7508476855e8b#cell-264).

I think having a localStorageView means that I can use that as the “authority source” instead of needing a fake source, as per your diagram.

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/2/23da3cd4a96dd78ce3c2ac686f38fa039f1dc10f.png)

Is it the intended way to use localStorageView, as the “authority”?

* * *

@mootari Thank you so much.

> and if desired, only the _source_ should be declared an Observable view.

I suppose the docs weren’t crystal clear for me at least. The _if desired_ doesn’t really carry the same meaning as “you should only have _one_ viewof cell”, which is much clearer!

However, your solution, I think works because it avoids chaining/transitive dependencies, it doesn’t seem to be because of the `viewof` usage. As you can see in the [“Solution” section](https://observablehq.com/@jmatsushita/transitive-reactive-input-dependencies#cell-50) using `viewof` everywhere seems to achieve exactly the same result.

I did implement your suggestion, using only `viewof` on the source, in the section “Follow up question” just below, and it seems to behave the same. Am I missing something important here? 🙂

> Programmatically setting a form element’s value however does not automatically dispatch an event.

Oh I see, hence the “set helper” I’ve seen around which both sets the value and fires a bubbling event, pretty much exactly like the `bind` code you linked. (Although I suppose it should be call the “set and dispatch helper” really).

It helps thank you! Maybe using @tomlarkworthy 's diagram and paragraph I copy pasted above would be a great addition to the docs!

---

<div class="post-metadata">

**Author:** ![tomlarkworthy](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/tomlarkworthy/32/5940_2.png) [@tomlarkworthy](https://talk.observablehq.com/u/tomlarkworthy)\
**Post date:** [December 14, 2023, 12:27pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/8 "2023-12-14T12:27:12Z")

</div>

normally I have localStorageView as a target. So for a coding system, `viewof code = Editor(...)` is the authority. localStorageView is bound to that, and if you have buttons injecting examples they should write into the editor viewof. If they write AND tell the editor to emit an event, the localStorageView should pick it up. At least in theory, sometimes there is nuance 😕

I’ll try and see if I can put an example together later but I am at work right now.

---

<div class="post-metadata">

**Author:** ![mootari](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mootari/32/581_2.png) [@mootari](https://talk.observablehq.com/u/mootari)\
**Post date:** [December 14, 2023, 6:01pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/9 "2023-12-14T18:01:59Z")

</div>

> [@jmatsushita](#):
>
> Am I missing something important here? 🙂

Yes, you likely didn’t look at the underlying generator value:

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/0/05cdaae9ae12e36ca77d4f6f764ee596558b5f09.png)

I recommend to have a look at this introduction to `viewof` which might help you approach these kinds of problems differently:

> **[What has viewof ever done for us?!](https://observablehq.com/@mootari/what-has-viewof-ever-done-for-us)**
>
> A short introduction to \`viewof\`, in response to this post. \`viewof\` is an Observable macro (i.e., a "magic word") that allows you to create user interfaces for your values. Observable cells by themselves are rather boring: they can only store...

---

<div class="post-metadata">

**Author:** ![tomlarkworthy](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/tomlarkworthy/32/5940_2.png) [@tomlarkworthy](https://talk.observablehq.com/u/tomlarkworthy)\
**Post date:** [December 15, 2023, 10:45pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/10 "2023-12-15T22:45:14Z")

</div>

Normally I would use localStorageView like this

```auto
viewof editor = Inputs.bind(
  PurescriptEditor(
    ""
    // [myDefaultTheme]
  ),
  localStorageView("code")
)

```

But this does not work with the PurescriptEditor because it is not setup as a view properly when it returns. There is some stuff going on in the background.

I put a basic setup for what you are trying to acheive here [Community Help / Tom Larkworthy | Observable](https://observablehq.com/@tomlarkworthy/community-help#cell-523) using a text component.

---

<div class="post-metadata">

**Author:** ![tomlarkworthy](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/tomlarkworthy/32/5940_2.png) [@tomlarkworthy](https://talk.observablehq.com/u/tomlarkworthy)\
**Post date:** [December 15, 2023, 10:57pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/11 "2023-12-15T22:57:21Z")

</div>

ahh I just need to await it. The other problem is the editor is not emitting an input even every time the document updates, which means the data channel is not tracking the editor content. Note how my variable is not synced to the editor code.

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/a/a6c1f244fdb673c36e850c075a5e1d86ed72c8f5.png)

Its that event that localStorageView looks for too. So localStorage is not informed of the editor changes and thus can’t save the content.

> **[Try Purescript](https://observablehq.com/d/9568798fb0fbd44c#editor)**
>
> Run purescript code in ObservableHQ using \`try.purescript.org\`'s compiler endpoint and @jmatsushita/purescript. Usage Modify the Source code in the Editor below. Click the \`compile\` button to send your changes to the try purescript compiler API....

I tried to write the rules of views here [Design Guidelines and Linter for Reusable UI Components / Tom Larkworthy | Observable](https://observablehq.com/@tomlarkworthy/ui-guidelines)

although there is not one for emitting the event when the user interacts. I supect there is an event inside but it has not set the bubbles:true flag on the even so its not leaving the component

Cool PureScript editor! Will be cool

---

<div class="post-metadata">

**Author:** ![tomlarkworthy](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/tomlarkworthy/32/5940_2.png) [@tomlarkworthy](https://talk.observablehq.com/u/tomlarkworthy)\
**Post date:** [December 22, 2023, 9:34pm UTC](https://talk.observablehq.com/t/transitive-synchronized-inputs/8597/13 "2023-12-22T21:34:00Z")

</div>

Oh I do have a backwritable code mirror view here [CodeMirror 6 View / Tom Larkworthy | Observable](https://observablehq.com/@tomlarkworthy/codemirror-6#CodeMirror)

I could not find it when searching 😕

I upgraded the example of binding localStorageView to it to support persisted code mirror

> **[Community Help](https://observablehq.com/@tomlarkworthy/community-help#cell-540)**
>
> Reactively update content within the same cell? you can manually use addEventListener to wire up reactivity as shown below @tomlarkworthy/view also has \`bindOneWay\` with a similar exampkle that acheive the below but with a functional transform 
> see...
