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>
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.