Skip to content


Simple table

In a simple table, you can aggregate your data with as many dimensions as your want and display the corresponding measures. You can also add computed measures. A computed measure ia a column that is obtained as a formula using other columns content. In the screenshot below (which is a folded table), the column average basket is a computed measure obtained with the formula: line[4]/line[3].


If you enable the folding option (in the rows folding menu), the user can click on the ± icons in the first column:

alt text

In a folded table, the blue row is the grand total, and pink rows are intermediate totals. The grand total is only displayed if the option Display total is enabled for at least one column. To hide the intermediate total of a column, use the column formatting option Hide intermediate total.

Free table

The free table lets you configure cells one by one. Each cell can be of mode:

  • text: the cell content is a simple text.
  • value: the cell content is obtained from one datasource query.
  • formula: the cell content is a formula based on other cells.

HTML mode

When the HTML mode is enabled for a cell, the HTML code provided will be rendered into this cell.

When a cell is in value mode, {{valueN}} can be used to obtain the Nth value configured in the data menu. Note that the Computing formula and the Numeral formatting are already applied to the value.

It's also possible to use simple expressions such as: {{value2>=0 ? "green" : "red"}} or to use any dashboard function.

Using values and numeral formatting

If you apply a numeral formatting (e.g. with option "12.34%" to format the value as a percentage), the corresponding {{valueN}} returns a string including the percentage sign. If you write {{valueN*2}} or {{valueN >0 ? "a" : "b"}} an error will be returned.

In this case, you need to convert valueN to a number. To do that, use the toNumber function, e.g.: {{toNumber(valueN)*2}}.


<div style="background-color:#fafafa;
            flex-direction: column;

    <div style="color:rgb(77, 144, 147); font-size:1.4vw">

    <div style="font-size:2.5vw; color:rgb(0, 96, 100)">

    <div style="font-size:1.2vw; color: {{value2>=0 ? "green" : "red"}}">
        <span class="fa fa-angle-double-{{value2>=0 ? "up" : "down"}}"></span>
        {{value2}} vs Month-1


By default, the popup (when you click on a marker) displays the Label column and a list of the selected measures. You can configure what is displayed in the popup by filling in the Popup HTML template field.

The HTML code provided can contain formulas inside double curly brackets: {{line[1]}}. The available variables are:

  • value: contains the value of the Label column
  • line[N]: contains the value of the Nth selected measure column



<strong>Population: </strong>{{line[1]}}
<strong>Altitude : </strong>{{line[2]}}

Custom widget

The custom widget lets you code your own widget. You just need to provide the HTML code, including javascript and CSS as needed.

Using third party javascript or CSS libraries

Of course you can use 3rd party libraries such as D3.js to code widgets exactly as you want.

However, you should only load libraries that are not already used by the Serenytics application, such as D3.js or Highcharts. You should not try to load a different version of a library already used by Serenytics (such as ChartJs, Angular, Lodash, and more). You should not either load a different version of a CSS library already used by Serenytics, such as Bootstrap.

If you are not sure, please contact Serenytics support. Otherwise your widget could break in a future upgrade of the Serenytics platform.

How it works

You just need to write your code as if you were using it on any other web page. The only communication with Serenytics happens when retrieving the data to display in your custom widget.

For that, you need to use the strings {{rows}} and {{headers}} in your code, and they will be replaced at execution by the actual data serialized in JSON.

If you use one or more 3rd party javascript librairies, you need to load them with our helper function serenyticsLoadAllScripts(list_of_urls, callback) as shown in the example using D3.js below.


    var rows = JSON.parse('{{rows}}');
    var headers = JSON.parse('{{headers}}');

    console.log('data rows:', rows);
    console.log('data headers:', headers);

If you have a data set where you selected two headers Country and Amount, the following code will be executed:

    var rows = JSON.parse('[["France",470], ["USA":2550]]');
    var headers = JSON.parse('[{"name":"Country","type":"str"},{"name":"Amount","type":"float"}]');

    console.log('data rows:', rows);
    console.log('data headers:', headers);

Complete example using D3.js

    For this example to work, you need to select 2 columns in the Data config menu.
    The first column will be used as labels and the second one as numerical values.

<div id="customWidget" style="overflow: auto; height: 100%;"></div>

    function main() {
        // --- Retrieve data from Serenytics template injection
        var rows = JSON.parse('{{rows}}');
        var headers = JSON.parse('{{headers}}');

        if (!rows) {
            console.log('data is not yet loaded');

        // --- Create a table with inline bars using d3.js

        var table ="#customWidget").append("table");

        // Create a table with rows and bind a data row to each table row
        var tr = table.selectAll("")
            .attr("class", "datarow");

        // Apply style to even rows
        d3.selectAll(".datarow").filter(":nth-child(even)").attr("class", "datarow even")

        // Create the label column
        tr.append("td").attr("class", "data name")
            .text(function (d) {
                return d[0];

        // Create the value column
        var formatValue = d3.format(".2f");
        tr.append("td").attr("class", "data value")
            .text(function (d) {
                return formatValue(d[1]);

        // Create the chart column
        var chart = tr.append("td").attr("class", "chart");

        // Create the div structure of the chart
        chart.append("div").attr("class", "bar");

        // Create the scale to compute bar width
        var xScale = d3.scaleLinear()
            .domain([0, d3.max(rows, function (d) {
                return d[1];
            .range(["0%", "100%"]);

        // Creates the chart bars"")
            .style("width", "0%")
            .style("width", function (d) {
                return xScale(d[1]);


    #customWidget .chart {
        width: 300px;
        padding-left: 20px;

    #customWidget .bar {
        height: 17px;
        float: left;
        background-color: steelblue;

    #customWidget table {
        font: 14px sans-serif;
        vertical-align: middle;
        text-align: left;
        border-collapse: collapse;

    #customWidget td,th {
        padding-top: 2px;
        padding-bottom: 2px;

    #customWidget tr.even {
        background-color: whitesmoke;

    #customWidget th {
        padding-left: 10px;

    #customWidget {
        padding-left: 10px;

    #customWidget td.value {
        text-align: right;