Skip to main content

Renderers and Cell Popovers

A Render (in org.apache.juneau.console.views) names how a column's value is painted into its cell. It has an id that selects a renderer, an optional meta map of string parameters, and an optional popover.

Built-in renderers​

The ids in SinkRenderAllowlist.BUILTIN_IDS are the renderers the runtime ships:

date, datetime, ts-zulu, bool, linked, truncate, json, decimal, tag, progress, pill, code.

  • linked builds an href from a template whose {property} tokens are filled from the row. Each substituted value is escaped, and the resulting URL is scheme-checked by the sink allowlist (see Security Model).
  • pill and tag render status chips using the same pill styling as <@tag> in the chrome. A pill never emits role="button".
  • edit:<actionId> shows the value with a pencil that turns the cell into an input (text, number or select, via the input and options meta). Enter or leaving the field saves through the named row action, sending the edited column as fields; Escape or an unchanged value cancels without a request. A failed save keeps the input open with the error beside it. The pencil follows the action's visibleWhen and enabledWhen. It is a cell renderer only and is not on the sink allowlist.
  • Dates render through Intl.DateTimeFormat in the browser, so they follow the user's locale.

Custom renderers​

Register a renderer before the view mounts. The definition is either a bare function (treated as the display facet) or an object with display, sort, filter, type and class facets:

JuneauViews.registerRenderer("stars", {
display: function (cellData, rowData, meta) {
const n = Number(cellData) || 0;
return "★".repeat(n); // display returns a markup string: escape anything that came from data
},
sort: function (cellData) { return Number(cellData) || 0; }
});

JuneauViews.registerRenderer(id, def) and JuneauViews.resolveRenderer(id) are defined in juneau-renders.js, which loads first in the views pack. A column that names an unknown renderer id logs a warning and falls back to the raw value. Because the display facet returns markup, a custom renderer must escape every value that came from row data; the built-ins all do.

Custom renderers apply to table cells. Field-grid fill sinks (the detail and region fields named by a RegionDef.Field.render) accept only the frozen built-in ids, and SinkRenderAllowlist.assertAllowed rejects anything else; see Security Model.

Cell popovers​

A CellPopover turns a cell into a trigger for a small popover. Set it on a Render through its popover field.

TypeFieldMeaning
CellPopovertitleThe popover heading.
CellPopoverfieldsThe PopoverField list to show.
PopoverFielddataThe row property to show.
PopoverFieldtitleThe label for that line.
PopoverFieldrenderA Render for the value, restricted to SinkRenderAllowlist.POPOVER_TEXT_IDS (date, bool, decimal, datetime, ts-zulu).

Popover fields are deliberately limited to text-only renderers: a popover cannot host a link, a code block or other interactive markup.

Render r = Render.of("truncate")
.popover(CellPopover.of(PopoverField.of("createdAt").title("Created").render("date")).title("Details"));