Observable Framework 1.0.0 GitHub

JavaScript: Display

The built-in display function displays the specified value.

const x = Math.random();

display(x);

You can display structured objects, too. Click on the object below to inspect it.

display({hello: {subject: "world"}, numbers: [1, 2, 3, 4]})

Calling display multiple times will display multiple values. Values are displayed in the order they are received. (Previously-displayed values will be cleared when the associated code block or inline expression is re-run.)

for (let i = 0; i < 5; ++i) {
  display(i);
}

If you pass display a DOM node, it will be inserted directly into the page. Use this technique to render dynamic displays of data, such as charts and tables. Here is an example displaying a text node created using the DOM API:

display(document.createTextNode(`Your lucky number is ${Math.floor(Math.random () * 10)}!`));

This is a contrived example — you wouldn’t normally create a text node by hand. Instead, you’d use an inline expression to interpolate a value into Markdown. For example:

Your lucky number is ${Math.floor(Math.random () * 10)}!

You’ll often pass display a DOM node when you’re using a helper library such as Observable Plot or Observable Inputs or a custom component (a function you’ve written that returns a DOM node) to create content. For example, the above can be written using Hypertext Literal as:

display(html`Your lucky number is ${Math.floor(Math.random () * 10)}!`);

The display function returns the passed-in value. You can display any value (any expression) in code, not only top-level variables; use this as an alternative to console.log to debug your code.

const y = display(Math.random());

The value of y is .

The value of `y` is ${y}.

When the value passed to display is not a DOM element or node, the behavior of display depends on whether it is called within a fenced code block or an inline expression. In fenced code blocks, display will use the Observable Inspector.

display([1, 2, 3]);

In inline expressions, display will coerce non-DOM values to strings and concatenate iterables.

${display([1, 2, 3])}

Implicit display

JavaScript expression fenced code blocks are implicitly wrapped with a call to display. For example, this arithmetic expression displays implicitly:

1 + 2 // implicit display

Implicit display only applies to expression code blocks, not program code blocks: the value won’t implicitly display if you add a semicolon. (Watch out for Prettier!)

1 + 2; // no implicit display

Implicit display also doesn’t apply if you reference the display function explicitly (i.e., we wouldn’t want to show 2 twice below).

display(1), display(2) // no implicit display

The same is true for inline expressions ${…}.

${1 + 2}

${display(1), display(2)}

Responsive display

In Markdown, the built-in width reactive variable represents the current width of the main element. This can be a handy thing to pass, say, as the width option to Observable Plot.

The current width is ${width}.

(Internally, width is implemented by Generators.width.)

For more control, or in a grid where you want to respond to either width or height changing, use the built-in resize helper. This takes a render function which is called whenever the width or height changes, and the element returned by the render function is inserted into the DOM.

<div class="grid grid-cols-4">
  <div class="card">
    ${resize((width) => `This card is ${width}px wide.`)}
  </div>
</div>

If your container defines a height, such as 240px in the example below, then you can use both the width and height arguments to the render function:

<div class="grid grid-cols-2" style="grid-auto-rows: 240px;">
  <div class="card" style="padding: 0;">
    ${resize((width, height) => Plot.barY([9, 4, 8, 1, 11, 3, 4, 2, 7, 5]).plot({width, height}))}
  </div>
  <div class="card" style="padding: 0;">
    ${resize((width, height) => Plot.barY([3, 4, 2, 7, 5, 9, 4, 8, 1, 11]).plot({width, height}))}
  </div>
</div>
If you are using resize with both width and height and see nothing rendered, it may be because your parent container does not have its own height specified. When both arguments are used, the rendered element is implicitly position: absolute to avoid affecting the size of its parent and causing a feedback loop.

display(value)

If value is a DOM node, adds it to the page. Otherwise, converts the given value to a suitable DOM node and displays that instead. Returns the given value.

The display function is scoped to each code block, meaning that the display function is a closure bound to where it will display on the page. But you can capture a code block’s display function by assigning it to a top-level variable:

const displayThere = display;

Then you can reference it from other cells:

Inputs.button("Click me", {value: 0, reduce: (i) => displayThere(++i)})

view(element)

The view function is a wrapper for display that returns a value generator for the given input element (rather than the input element itself). For example, below we display an input element and expose its value to the page as the variable text.

const text = view(html`<input type="text" placeholder="Type something here">`);
text // Try typing into the box above

When you type into the textbox, the generator will yield a new value, triggering the reactive evaluation of any code blocks that reference text. See Inputs for more.