Learn Observable JavaScript with Observable notebooks

Free, hosted Observable notebooks provide an interactive experience and lots of open-source Observable JS code you can reuse and learn from. Here's how to get started.

Learn Observable JavaScript with Observable notebooks.

In the beginner's guide to using Observable JavaScript, R, and Python with Quarto, I outlined how to use Observable within a Quarto file. However, one of my top tips for Quarto users learning Observable JavaScript is to write code on the Observable community website. Even if you only plan to use Observable JavaScript in Quarto documents, it's a good idea to set up a free account and use the tools there. The code snippets alone make having an account worthwhile, and they'll help you learn the code required for basic tasks.

Another advantage of having an account at ObservableHQ.com is that you can quickly run a single notebook cell to see its results. This can be a useful timesaver compared with coding in a Quarto file. In RStudio, you can't currently run individual ojs cells in a Quarto document the way you can with R and Python cells. You need to render an entire document to see the results of ojs cells.

An RStudio spokesperson said via messaging that Observable notebooks are the best interactive experience to execute Observable-specific code. "I see {ojs} chunks in Quarto as a way of integrating some JavaScript/Observable into R/Python Quarto documents, or for integrating a JavaScript-heavy notebook into a larger project such as a book or website, beyond a single notebook output."

Once you’ve written your code in a hosted notebook on the Observable community website, you can copy and paste it into a Quarto document. Even slicker, you can import a function or a named variable from any public notebook—not just your own—into your notebook or Quarto document and use it there.

This article takes you step by step through how to create a hosted Observable notebook, add your own JavaScript components, and then import code from public notebooks for reuse. 

Step 1: Create a new notebook at ObservableHQ.com

To start, you will need a free account at ObservableHQ.com. Once you have an account, click New on the top right of your screen to create a new notebook. You’ll see a bunch of templates as well as the option to start with an empty notebook.

Blue pin in left margin next to code

Figure 1. The colored-in pin means code is "pinned" open to view.

If you choose the empty notebook, you should see one notebook “cell” with # Untitled. That single # is Markdown's symbol for large headline text. You can go ahead and change “Untitled” to whatever you want to call the notebook. Mouse over that area of the document and you should see a little pin in the left margin. That “pins” the code to be visible, as shown in Figure 1. If you click a colored-in pin, it is “unpinned” and the code is no longer visible. (The code still exists—click the three-dot menu next to the cell, find the pin, and click it. You will see that the code is pinned and visible again.)

If you click the triangle to the right of the cell, you can run the code to see the results, in this case, it's just the headline text. If you’ve used Jupyter notebooks or R Markdown, one noticeable difference is that results show up above the cell, not below it. That can take a little getting used to.

Step 2: Add a new Observable JS cell to the notebook

If you mouse over a pinned-open cell, you should see a clickable option that can change a cell's mode. Choices are Markdown, shown as multiple horizontal lines, HTML as <>, and JavaScript as {}. Below and above that you’ll see plus (+) signs that let you add a new cell to the notebook. Click the lower plus sign to add a new cell below the headline. This is one place where helpful tools for code snippets appear.

Figure 2 shows some of the available options for an Observable JavaScript cell.

Some available options for a JavaScript cell in Observable. List includes Data: File attachment, fet Sharon Machlis, Foundry

Figure 2. Some options for an Observable JavaScript cell.

If you choose File Attachment—>Upload a local file you'll get a dialog to select and upload a local file. Once you do so, code that accomplished the upload should pop into the cell. You should see two lines: one that says something like


your_file_name = Array(32) [Object, Object, Object . . . ]

and another like


your_file_name = FileAttachment("your_file_name.csv").csv()

That first line is the result of your code, an array of JavaScript objects. If you click the triangle next to Array, it expands so you can view your data.

Step 3: Add a JavaScript table to the notebook

Add another JavaScript cell, scroll down, and select the JavaScript table option under Tables. The code viewof table = Inputs.table(cars) should pop into the cell. If you run that, you’ll get a table of the built-in cars data set. Change cars to the name of the data you imported, and you’ll get a table with your data.

If you click the question mark in a circle at the bottom of the list of icons in the right margin (or just press the ? key while the cursor isn’t in a cell), you’ll get a list of help files. The "Add a table” help file explains that Inputs.table() displays the table. It can accept additional options such as sort. There’s a link in the table help text to a notebook with more info about Input: Table.

The same ? help text guides you on how to add a chart or interactive slider from the built-in Observable Plot library.

Step 4: Import JavaScript components for reuse

You can use the site's search function in the top navigation menu to look for notebooks that have graphics, data, or other things you might like to learn from or reuse. Under the Observable website's terms of service, code in public notebooks is available for import and use in your notebooks hosted on ObservableHQ.com. If you want to use that code in an external Quarto document, make sure it’s licensed for reuse or that you otherwise have permission. 

Import a public function

To use someone else's function, add the following to your notebook and start using the function with any needed arguments as usual:


import {TheFunctionName} from "@user/notebook-name"
 

You can rename the function, as well, using the syntax: 


import {their_function as my_function}
from "@username/notebook_name"

You can then use that code with my_function(mydata) (adding any additional function arguments if needed).

Note that you can use the same import {TheFunctionName} from "@user/notebook-name" code in a Quarto document's ojs code chunk, not only on ObservableHQ.com.

Import a cell

In a notebook on ObservableHQ.com, clicking the three-dot menu to the left of a named cell should show an option to Copy Import if a cell is copyable. As shown in Figure 3, clicking that will give you the correct import code.

Menu showing an option to 'Copy Import' below 'Unpin' and 'Add comment'

Figure 3. Click the three-dot menu to the left of a cell. You will see an option to copy the code to import that cell to another notebook.

Reusing code in Observable notebooks

Some of the notebooks authored by Observable developers don't display licenses for reuse. Mike Bostock, the co-founder and CTO of Observable, Inc.,  told me that’s probably because developers tend to view them as tutorials to read and not as code to reuse. It's not that the company doesn't want others to use its code off-platform.

“We love seeing people create new ways to use Observable [JavaScript] in other technologies,” Bostock said. If you'd like to use code in a notebook without an assigned open-source license, Bostock added, "We encourage people to reach out to the author."

Import also works with data, graphics, and even text from another notebook, whether yours or someone else's.

“Think of a cell as a function, except the function has no arguments,” is the advice from the Observable’s not JavaScript documentation. Bostock also has an example with explanations in his Bar Chart, Horizontal notebook.

This way of thinking can help you modularize your own code as well as reusing work from others. And, you can "rewrite code on-the-fly to substitute values when importing using Observable’s import-with syntax," said Bostock. "This allows you to take content from another notebook, such as a chart, and replace its data with your own, as long as your data has an identical structure (the same column names and types)." If your data isn't in the needed format, use something like array.map to transform it into what's needed. 

See Observable’s Introduction to Imports for more details and timelyportfolio’s Quarto example of reusing a data summary table with graphics to produce something like what's shown in Figure 4.

Table with graphical visualizations of summary stats for data columns

Figure 4. A table created by the imported SummaryTable function.

You just need two lines of code, each in its own notebook cell:


import { SummaryTable } from "@observablehq/summary-table"
SummaryTable(mydata)

The two lines must be in separate cells on ObservableHQ.com (they can be in a single Observable cell in a Quarto document).

Thanks to Bob Rudis, vice president of data science at security firm GreyNoise Intelligence, you can even save an Observable notebook as a local Quarto document with a Rust application or Chrome extension, Quartize.

Language support for Observable notebooks

I asked Mike Bostock whether Observable, Inc. is considering hosting Quarto or other documents that would incorporate R and/or Python, as well as JavaScript. 

"We definitely talk about it a lot," Bostock said, "but there are some considerations … We are at heart web-based and focused on running code in the client," aiming to offer an experience that is "fast and fluid." Bostock did say, however, that he is watching WebAssembly projects like Pyodide that offer in-browser language computations.

For now, at least, the Observable web platform supports JavaScript, Markdown, and HTML only. Next: Learn data visualization with Observable JavaScript.

Copyright © 2022 IDG Communications, Inc.