Custom visual templates

A template is a custom visual that runs no author JavaScript: you write visual.html, visual.css and options.json, and DataPrism fills the markup with the tile's rows. This page is the reference for the template language. For the editor around it, see The custom visual Studio; for what a tile receives, Custom visual options, data and limits; and for custom visuals as a whole, Custom visuals and the visual library.

Interpolation and values

Filters

Date patterns

Expressions

Directives

Every directive is an attribute on the element it affects.

Rows, groups and totals

A small example

html
<div data-uni-repeat="rows">
  <span data-uni-select="Category">{{ Category }}</span>
  <strong>{{ Amount | number:2 }}</strong>
</div>

When a template fails

Questions, answered

How do I show a number with grouped digits and decimals?

Use the number filter with the decimals you want: {{ Total | number:2 }} draws with grouped digits and two decimals, such as 1,234.57. The argument must be a whole number from 0 to 20. An empty value draws nothing, and text that is not a number passes through unchanged.

Why does a very long number keep every digit?

A value that arrives as a digit string of 16 or more characters is grouped as a string rather than turned into a number, so nothing is rounded and no digit is lost: a value such as 92,233,720,368,547,758,070 draws in full.

Why do month names draw in English?

Month and weekday names always read in English, because the template locale is fixed, whatever the viewer's language.

Will a date shift for viewers in another timezone?

No. Dates draw from their wall-clock fields, as written, and are never converted to the viewer's timezone. A date that already carries a zone in its text draws from its wall-clock fields too.

How do I repeat a block for every row?

Put data-uni-repeat="rows" on the element; it draws once per row the tile receives. Inside it, the row's fields are in scope by name and index gives the item's position. To repeat per group of a field instead, use groups('Field').

How do I show an element only under a condition?

Add data-uni-if with the condition. The element draws while the expression is true and is left out otherwise, on plain elements and inside repetitions alike.

How do I group rows and total a column?

Repeat over groups('Field'). Each group carries g.key, g.count, g.rows and g.sum(...) for totals across it, and the scope carries count() and sum(...) as well.

Which functions can I call in an expression?

Only the built-in ones. A call to anything else fails to compile, and the error lists the functions you may use.

How do I make an element select a value when it is clicked?

Put data-uni-select="<Field>" on it and keep that field in scope through a row or a group, usually by working inside a repetition. A click then selects the value; Ctrl or Cmd adds to the selection, and data-uni-suppress="select" stops a click from selecting.

Can a value from my data inject markup into the visual?

No. {{ ... }} draws every value as text, so markup a value carries stays visible as text. Only {{{ ... }}} draws markup, and its output passes the sandbox's sanitiser first.

Is there a limit to how much a template can draw?

Yes, 20,000 nodes per render, elements and text together. Past that the render stops with one error and keeps what it built so far, so a very large listing draws partially and reports more than 20000 nodes.

Why was my url() style dropped?

A style value may not contain url(), expression() or javascript:, so the element is dropped and the error reads style value for '<name>' may not contain url(), expression() or javascript:. Load outside images through data-uni-src instead.