# update value of another input when an input is triggered in a multi input single object

**URL:** <https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532>\
**Category:** Help\
**Created:** [November 25, 2023, 6:21pm UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532 "2023-11-25T18:21:50Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![cittadhammo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/cittadhammo/32/9381_2.png) [@cittadhammo](https://talk.observablehq.com/u/cittadhammo)\
**Post date:** [November 25, 2023, 6:21pm UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/1 "2023-11-25T18:21:50Z")

</div>

I have a notebook [Clear Mountain Monastery – Org. Chart / Cittadhammo | Observable](https://observablehq.com/d/3e91821ef6028f2c) where I would like that when the **darkMode** checkbox is checked, it changes the value of some of the other inputs, for example the **colorSeed** range.

If the input are in different cells, I can use a ternary operator (see [version 1062](https://observablehq.com/d/3e91821ef6028f2c@1062)):

```auto
viewof colorSeed = Inputs.range([0, 100], {
    label: "colorSeed",
    step: 1,
    value: darkMode ? 50 : 2
  }),

```

Alas, as I am using a single multi input statement with a objet **p** now, I run into a ciruclar error: **p.darkMode, p.colorSeed…**

I have tried using () =\> this.darkMode or [Custom Input Example / Toph Tucker | Observable](https://observablehq.com/@tophtucker/custom-input-example) or [Synchronized Inputs / Observable | Observable](https://observablehq.com/@observablehq/synchronized-inputs), but unsuccessfully so far.

What would be the best way to proceed?

Thank you for your help.

---

<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:** [November 26, 2023, 10:36am UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/2 "2023-11-26T10:36:40Z")

</div>

I would first try to approach this from a conceptual point of view. From what I can tell your Dark Mode toggle acts more like a preset, since I can change the affected sliders afterwards without the toggle getting deselected, in which case I would make it a button (and maybe even move it above the form).

If on the other hand it is in fact a modifier then I would recommend to not change the sliders, but apply the changes in your final calculations.

If you still need to include the button or toggle in your form, then I would recommend to use [Inputs.form()](https://github.com/observablehq/inputs#inputsforminputs-options) with the `template` option instead for this particular scenario:

```js
viewof mySettings = Inputs.form({
  optionA: Inputs.number([0, 100], {label: "Option A", value: 10}),
  optionB: Inputs.range([20, 60], {label: "Option B"})
}, {
  template: ({optionA, optionB}) => {
    const set = (input, value) => {
      input.value = value;
      input.dispatchEvent(new Event("input", {bubbles: true}));
    };
    const button = Inputs.button([["Set option B", () => set(optionB, 55)]]);
    return htl.html`<div style="display:flex;gap:32px">
      <div>${optionA}</div>
      <div>${[button, optionB]}</div>`;
  }
})

```

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

---

<div class="post-metadata">

**Author:** ![cittadhammo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/cittadhammo/32/9381_2.png) [@cittadhammo](https://talk.observablehq.com/u/cittadhammo)\
**Post date:** [December 2, 2023, 12:24pm UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/3 "2023-12-02T12:24:55Z")

</div>

Thank you very much!, I have simplify [the input](https://observablehq.com/d/3e91821ef6028f2c) by separating into two blocks as suggested.

Another thing that would be nice is to enable the input scroll Zoom (`p.scrollZoom`) when fullscreen is enable (I don’t want user to be stuck when scrolling down the page and the chart start zooming instead). I have tried the following function:

```auto
fullscreen = {
  const button = html`<button> Go Full Screen`;
  button.onclick = () => {
    button.parentElement.nextElementSibling.requestFullscreen();
  };
  return button;
}

```

But it fails with a simple redefinition of the` p.scrollZoom` variable. I think that using `input.dispatchEvent` would be the way forward, but it is pretty obscure how this works.

The current fullscreen option is imported from [Fullscreen / Fil | Observable](https://observablehq.com/@fil/fullscreen)

Thanks for your help

---

<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 2, 2023, 2:27pm UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/4 "2023-12-02T14:27:56Z")

</div>

From what I can tell d3-zoom offers no method to toggle zooming or ignore a zoom event - the internal transform will always get updated even if you choose to not apply it.

My recommendation would be to conditionally remove the event handlers on fullscreen change:

```js
const zoom = d3.zoom().on("zoom", zoomed);

const toggleZoom = enabled => enabled
  // Attach zoom handlers
  ? svg.call(zoom)
  // Remove all *.zoom event handlers
  : svg.on(".zoom", null);
// Initialize
toggleZoom();
  
svg.on("fullscreenchange", (e) => {
  // Enable zooming if svg.node() is the fullscreen element
  toggleZoom(e.target === document.fullscreenElement)
});

```

---

<div class="post-metadata">

**Author:** ![cittadhammo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/cittadhammo/32/9381_2.png) [@cittadhammo](https://talk.observablehq.com/u/cittadhammo)\
**Post date:** [December 2, 2023, 3:08pm UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/5 "2023-12-02T15:08:02Z")

</div>

Ok, interesting, I have tried to add:

```auto
 function zoomed({ transform }) {
    svg.attr("transform", transform);
  }

  // --- alternative zoom from https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/3 independant of toogle and allow zoom only on fullscreen --- //

  document.addEventListener("fullscreenchange", function () {
    console.log("fullscreenchange event fired!");
  });

  const zoom = d3.zoom().scaleExtent(0.1, 8).on("zoom", zoomed);

  const toggleZoom = (enabled) =>
    enabled
      ? // Attach zoom handlers
        svgOrigin.call(zoom)
      : // Remove all *.zoom event handlers
        svgOrigin.on(".zoom", null);
  // Initialize
  toggleZoom();

  document.addEventListener("fullscreenchange", (e) => {
    // Enable zooming if svg.node() is the fullscreen element
    console.log(e);
    console.log(document.fullscreenElement);
    console.log(e.target === document.fullscreenElement);
    toggleZoom(e.target === document.fullscreenElement);
  });

```

at the end of the code of the [chart cell](https://observablehq.com/d/3e91821ef6028f2c), with a few testing log and the log says it works and toggleZoom() is supposed to be ON, but there is no zoom or pan in fullscreen…

---

<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 3, 2023, 6:22pm UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/6 "2023-12-03T18:22:54Z")

</div>

Establish a baseline by testing directly with

```auto
svgOrigin.call(zoom)

```

before you start testing with toggleZoom(). You’ll notice that zooming is already broken here, and if you log `transform` in `zoomed` you’ll see several NaN values because `scaleExtent` expects an array:

```js
  const zoom = d3.zoom().scaleExtent([0.1, 8]).on("zoom", zoomed);

```

Also keep an eye on your JS console. There are several errors that you may want to take care of first.

---

<div class="post-metadata">

**Author:** ![cittadhammo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/cittadhammo/32/9381_2.png) [@cittadhammo](https://talk.observablehq.com/u/cittadhammo)\
**Post date:** [December 4, 2023, 9:16am UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/7 "2023-12-04T09:16:11Z")

</div>

Very good ! you were right, I made a mistake in the argument of the function scaleExtent(). It [all works nicely now](https://observablehq.com/d/3e91821ef6028f2c). Thank you very much for your help.

If you have more patience, I have been trying to reset the position of the chart to (0,0) and scale 1 when exiting the full screen mode. I have tried using the [translateExtent()](https://www.d3indepth.com/zoom-and-pan/) function. It does the job but I wonder if there is a better solution (it is a bit complicated as there is a toggle p.scollZoom that allow to zoom and pan in no fullscreen mode) :

```auto
const zoom = d3.zoom().scaleExtent([0.5, 8]).on("zoom", zoomed);
const zoomNoFull = d3
    .zoom()
    .scaleExtent(p.scrollZoom ? [0.5, 8] : [1, 1])
    .translateExtent(
      p.scrollZoom
        ? [
            [-(p.width / p.zoom), -(p.width / p.zoom)],
            [p.width / p.zoom, p.width / p.zoom]
          ]
        : [
            [0, 0],
            [0, 0]
          ]
    )
    .on("zoom", zoomed);

const toggleZoom = (enabled) => {
    if (enabled) {
      // Attach zoom handlers
      svgOrigin.call(zoom);
    } else {
      // Remove all *.zoom event handlers
      svgOrigin.on(".zoom", null);
      svgOrigin.call(zoomNoFull);
    }
  };

```

Anyway, thank you for your help, awesome. I wish there would be a template for basic chart display with options, fulscreen mode, dowload high resolution, etc.

Best regards

---

<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 4, 2023, 10:23am UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/8 "2023-12-04T10:23:15Z")

</div>

Be sure to take a look at the [d3-zoom docs](https://d3js.org/d3-zoom#zoom_transform). There you’ll find an example to reset a zoom transform, which you need to apply _before_ you remove the handlers so that your SVG can still update:

```js
    } else {
      svgOrigin.call(zoom.transform, d3.zoomIdentity);
      // Remove all *.zoom event handlers
      svgOrigin.on(".zoom", null);
    }

```

---

<div class="post-metadata">

**Author:** ![cittadhammo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/cittadhammo/32/9381_2.png) [@cittadhammo](https://talk.observablehq.com/u/cittadhammo)\
**Post date:** [December 4, 2023, 12:10pm UTC](https://talk.observablehq.com/t/update-value-of-another-input-when-an-input-is-triggered-in-a-multi-input-single-object/8532/9 "2023-12-04T12:10:05Z")

</div>

That is much better, thank you !
