How to use div to customize Inputs positions in Framework

Hi,

My question is how to organize multiple Inputs such as a text and a range on the same level right beneath a P5 sketch inside Observable Framework. I know very little of html and document, and below is all I can do to put them closer.

I can use a div and .parent("displayText") to display the sketch to where the div is.

But I have no idea how to put all Inputs items together on the same level. More specifically, I don’t know how to do .parent("divName") for the inputs below.

See Inputs.form for combined inputs.

(Also please don’t share AI-generated code, as it only muddies the discussion and takes a high psychological toll on humans who try and provide support.)

2 Likes

Thanks a lot for the help and also the suggestion! I am taking down the AI generated code now.

1 Like

Thanks @Fil , now form can help to group all the inputs together vertically as seen in the image below.

However, I still wonder 2 things:

  • how to organize them horizontally on the same horizontal level.
  • how to put them onto a div so that I can put them wherever I want

From a cursory search, this thread may be of help: Input.form Template option modification and examples - #3 by ciscorucinski

1 Like

Thank you so much @dleeftink for your links and suggestions, I have made some progress using Inputs.form with a template function, please see the image below.


Now, One last thing I would dream to have is Inputs.bind to work inside Framework, however, inside Framework docs, there is no Inputs.bind which seem only exist in Notebook. Is it possible to make this Notebook on Inputs.bind work inside Framework? @Fil @mbostock

What is it youre trying to do with Inputs.bind?

It’s slightly different in Framework since we don’t have the viewof keyword, and must give a name to the original input we want to bind on (instead of using viewof x).

See https://observablehq.observablehq.cloud/pangea/support/inputs-bind for a working example.

1 Like

It it me or does the sliding action not work on mobile? I can press the track to have the slider jump to its new location, but the sliding interacitivity does not work (Chrome/Android).

It works for me on iOS

Here are two possible approaches.

First, you can define multiple inputs in the same code block, and they are displayed together. They will be stacked vertically.

```js
const r = view(Inputs.range([0, 255], {step: 1, label: "r"}));
const g = view(Inputs.range([0, 255], {step: 1, label: "g"}));
const b = view(Inputs.range([0, 255], {step: 1, label: "b"}));
```

Second, you can define detached inputs and their associated reactive variables, and then place those inputs anywhere you like on the page using an inline expression ${…}. See the view(element) documentation for a live example.

```js
const nameInput = html`<input type="text" placeholder="anonymous">`;
const name = Generators.input(nameInput);
```

<div class="card" style="display: grid; gap: 0.5rem;">
  <div>Enter your name: ${nameInput}</div>
  <div>Hi <b>${name || "anonymous"}</b>!</div>
</div>

Inputs.form or Inputs.bind are in some ways workarounds for the restrictive nature of Observable notebooks where each cell can only display one thing and define one named value. In Observable Framework, code blocks can define and display as many things as you like, and using interpolated expressions, you can display content anywhere, not just at the top level.

One of the current limitations of code blocks and inline expressions is that they currently generate a wrapper element (either a DIV or a SPAN) around the displayed content. In the future, I’d like to eliminate this wrapper element, which would let you place a code block or inline expressions within a container with CSS grid, giving greater flexibility. Please upvote #11 if you are interested in this feature.

1 Like

You can also find an example of using Inputs.bind here:

https://observablehq.com/framework/javascript#inline-expressions

The input and its reactive variable are declared in JavaScript:

const numberInput = Inputs.input(0);
const number = Generators.input(numberInput);

And then you can embed in Markdown like so:

${Inputs.bind(html`<input type=range style="width: 120px;">`, numberInput)}

And likewise reference the reactive value as:

${number}
2 Likes