Built-in reactivity is one of Observable JavaScript's biggest value adds. In my two previous articles, I've introduced you to using Observable JavaScript with R or Python in Quarto and learning Observable JavaScript with Observable notebooks. In this article, we get to the fun part: creating interactive tables and graphics with Observable JavaScript and the Observable Plot JavaScript library.
I usually think of a table as an “output”—that is, a helpful way to view and explore data. In Observable, though, a basic table can also be considered an “input." That’s because Observable tables have rows that are clickable and selectable by default, and those selected values can be used to affect plots and other data on your page. This helps explain why the function generates a table.
The default table is sortable if you click column headers, and shows several rows along with a scroll bar.
To specify the number of rows you'd like visible in the scrollable window, add the argument. The argument shown here displays the first 20 rows in the scrollable window:
Note that table options are enclosed in curly braces, even if there's only one option.
To choose specific columns to appear in a table, add a option to with the syntax:
Note that is followed by a JavaScript array, which is created by brackets similar to Python and not as in R. Column names need to be in quotation marks.
To rename columns, use with the following syntax:
To combine selecting and renaming columns, use both and :
The resulting default will look something like this, using data for US states and their populations:
Several other options are available for , including sorting and reverse-sorting, which you can do with the syntax: .
If you’re coding in a hosted notebook on ObservableHQ.com, you'll see that there are other built-in table types available for a cell, such as Data Table cells. Some of these types are part of the Observable web platform. They are not standard JavaScript functions and you won't be able to use them in a Quarto document. How can you tell? If you don’t see a line of code pop up after you create a table, it’s probably not available off-platform unless you code it yourself.
One of Observable's biggest value adds is its built-in reactivity. To create an interactive filter, the syntax is usually along the lines of
where is one of the built-in Observable filter types.
Filter types include checkbox, radio, range (for a slider), select (for a dropdown menu), search, and text (for free-form single-line text). Arguments for the filter function depend on the filter type.
makes the filter reactive. In his notebook A brief Introduction to viewof, Mike Bostock, CTO and founder of Observable, Inc., writes: "The way to think about is that, in addition to the that displays the input element, creates a second hidden cell that exposes the current value of this input element to the rest of the notebook."
creates both a text search box and a reactive data set that is automatically filtered and subsetted based on what a user types into the box. For R Shiny users, it’s as if a single function created both the text field UI and the server-side code for the reactive data set.
To use the reactive data set elsewhere in your code, simply refer to instead of , such as:
The above code generates a table from . The data set and table will update whenever a user types something into the search box, looking for matches across all the columns.
You can use that filtered data set multiple times on a page in various kinds of plots or in other ways.
is somewhat of a special case because it is designed to filter a data set in a specific way, by looking across all columns for a partial match. That's simple but may not be what you want, since you may need to search only one column or create a numerical filter.
For example, if you want a dropdown list to display possible values from one column in your data and filter the data by that selection, the code to create that dropdown needs to specify what values to display and which column should be used for subsetting. The code below creates a dropdown list based on sorted, unique values from the column in the data set:
As you might conclude from the variable name , this both creates the dropdown list and stores whatever value is chosen, thanks to .
applies a function to each item in an array, in this case getting all the values in ’s .
The above code uses JavaScript’s newer “arrow” (=>) format for writing functions. You could write the same code with JavaScript's older and syntax, as well:
Once again, don’t forget the before defining if you want the code to be reactive.
Unlike , which automatically acts upon an entire data set, only returns values from the dropdown. So, you still need to write code to subset the data set based on those selected values and create a new, filtered data set. That code is the same as if you were filtering a static data set.
As explained in Quarto's Observable documentation: "We don't need any special syntax to refer to the dynamic input values, they 'just work', and the filtering code is automatically re-run when the inputs change." You don't need before the statement that defines the data set; use it only before the .
If you prefer, you can use JavaScript’s older syntax with and :
You can use the filtered data set as you would a static data set, such as:
Check out the Hello Inputs and Observable Inputs notebooks for more about .
Including the value of a variable in a text string to generate dynamic text can be useful if you want to create a graph headline or summary paragraph that changes with your data. If a variable is defined in an code chunk, you can include that variable’s value within a Quarto ojs code chunk by enclosing the variable name with , such as:
Here, indicates that what’s contained within the backticks should be evaluated as Markdown text, not JavaScript code. You can also use before the backticks if you want to write HTML that includes a variable value, such as:
The value of x is ${x}.
Note that and are only needed in Quarto documents. If you are using a hosted notebook at ObservableHQ.com, you can choose Markdown or HTML for the cell mode so you don’t need to signify or .
You should use backticks on ObservableHQ.com to signify that the contents are text and not code if you are storing text in a variable inside a notebook's JavaScript cell.