observable js input options based on selected input before

200 Views Asked by At

I'm pretty new to observable js (or rather anything js / html related), so this might be a very stupid question and I might not have grasped some of the core concepts. I'd be super thankful for any hints on what I'm getting wrong.

I'm trying to build two Inputs, so that the viewer can first choose which dataset they want to inspect and then based on their dataset selection decide on what variables they are interested in. I can't get the second aspect to work though.

This is the code I have written so far, and I get an error when I try to define the options based on the dataset with const.

viewof dataset = Inputs.select(
  ["Datset 1", "Dataset 2", "Dataset 3"], 
  {label: "Which Dataset would you like to use?", value: "dataset"}
)

viewof variables = Inputs.select(
  [], 
  {label: "Which Variable would you like to inspect?", value: "variable"}
)

{const datasetOptions = 
  "Dataset 1": ["a", "b"],
  "Dataset 2": ["c", "d"],
  "Dataset 3": ["c", "f", "g"]
}

dataset.on("change", () => {
  variables.options = datasetOptions[dataset].options;
  variables.value = variables.options[0];
});

This is written in ojs (@observablehq) in a quarto document in RStudio.

I would appreciate any hints on what I should look into for a solution! I really appreciate it!

2

There are 2 best solutions below

1
Lilia Schon On

To work in Observable, you must declare your datasetOptions object like so:

 datasetOptions = ({
  "Dataset 1": ["a", "b"],
  "Dataset 2": ["c", "d"],
  "Dataset 3": ["c", "f", "g"]
})

You can read more here on how the syntax for Observable JavaScript differs from vanilla JavaScript: https://observablehq.com/@observablehq/observable-javascript.

Also, some features of the Observable website are not available in the OJS language. For help related to OJS in Quarto, this discussion forum could be helpful: https://github.com/quarto-dev/quarto-cli/discussions/categories/q-a

1
Mark McClure On

I think the code block below should get you close to what you want. Note that Observable has a built in reactivity, which is one of the things that makes it super easy to use. If you have

viewof x = Inputs...

Then the variable x in subsequent Javascript code will refer to the value of x. In particular, you often don't need code like

my_input.on("change", () => {...})

because the change is handled by the Observable runtime.

---
title: "Selecting Selects"
author: "MM"
format:
  html:
    echo: false
---

**Which dataset would you like to use?**
```{ojs}
viewof dataset = Inputs.select(
  ["Dataset 1", "Dataset 2", "Dataset 3"],
  {
    // Labels should generally be short and concise.
    label: "Dataset:", 
    value: "Dataset 1"
  }
)
```

**Which variable would you like to use?**
```{ojs}
viewof variables = Inputs.select(
  // the `dataset` variable refers to the
  // value of the previous inputs.
  datasetOptions[dataset],
  {
    value: "variable",
    label: "Variable:"
  }
)
```

---

Here are your results:

  - Dataset: ${dataset}
  - Variables to choose from: ${datasetOptions[dataset]}
  - Selected variable: ${variables}


```{ojs}
datasetOptions = ({
  "Dataset 1": ["a", "b"],
  "Dataset 2": ["c", "d"],
  "Dataset 3": ["c", "f", "g"]
})
```