Create custom charts

Custom chart element titled 'Custom chart' displaying a large '40%' percentage in white text with 'Practice nurses' subtitle on a solid blue background tile.

You can use HTML and Markdown to build custom visuals in Protobi. In this tutorial we will show how to create simple custom charts, including the above graphic. 

Simple example with HTML

1. Create a new element 

Protobi workbench interface displaying a custom_chart element with a single data row showing '[NA]' at 100% (N=100) represented by a blue horizontal bar.

2. From the JSON editor, set the chartType to "BasicElement". Each custom chart starts with steps 1 and 2. 

Element properties dialog for 'custom_chart' displaying JSON configuration with line 11 highlighting chartType property set to 'BasicElement'.

3. Open the HTML content editor by selecting the element and using the shortcut SHIFT + x + c . 

Element properties dialog titled 'Element properties: glossary' showing an empty JSON editor with only line number 1 visible.

4. Below, we have an example with two levels of HTML heading tags, and a paragraph tag.

Element properties dialog for custom_chart displaying HTML code with heading tags (<h1>Title</h1>, <h2>Subtitle</h2>) followed by Lorem ipsum placeholder text wrapped in paragraph tags.

The result:

Custom chart element displaying rendered HTML output with blue 'Title' heading, lighter blue 'Subtitle' heading, and black Lorem ipsum paragraph text below.

Read Add a project intro to see how a simple HTML element can enhance your project.

Markdown

If you prefer to use Markdown syntax, add the "markdown" attribute to JSON and set it to true

Element properties dialog displaying JSON configuration with chartOptions object containing width: 400 and height: 360, plus a content property with HTML string including Title, Subtitle, and Lorem ipsum text. Line 16 shows 'markdown': true highlighted.

With the "markdown" attribute set to true, you can enter Markdown or HTML syntax in the content editor. 

Below we create the same boiler text as the first example, but use Markdown syntax instead. Hash symbols create headings, and new paragraphs are created using a blank line.

Element properties dialog displaying markdown-formatted content with '# Title' and '## Subtitle' heading syntax, followed by Lorem ipsum paragraph text without HTML tags.

Square graphic with static text

You can use HTML  to create custom shapes with bold text. The custom chart below is an HTML element, with the percent and label added as static text. 

Note, this chart won't respond dynamically to changes to the data. 

Custom chart element with header 'custom_chart1' showing a blue square tile containing large white '40%' text and 'Practice nurses' subtitle.

Expand the panel to see the code for custom_chart1. Scroll horizontally to view the code in its entirety.

Square graphic with static text

<div class="badge" style="width: 200px ; height: 200px; background-color: #39C; margin: 20px; text-align: center">
   <div class=qty style="font-size: 96px; color: white; font-weight: bold">40%</div>
   <div class=label style="font-size: 16px; color: white;">Practice nurses</div>
</div>

Delete

Square graphic with a dynamic data point

Add data to your custom charts that will react dynamically to current filters. For the custom_chart1 example above, we can edit the HTML to make the percent frequency dynamic.

Below, we pressed on only those respondents from the Mid Atlantic Region, and the percent in custom_chart1 responds dynamically to that filter.

Protobi workbench displaying two elements: custom_chart1 showing '22%' with 'Practice nurses' label, and a Region question showing NHS regions list with Mid Atlantic selected at 100% (N=18).

For the chart to reference the correct data column (i.e. S1), we first set the "field" in the Edit properties dialog.

More properties dialog for custom_chart1 displaying configuration fields including key: 'custom_chart1', displayKey: 'text', field: 'S1', and type dropdown set to '(default)'.

Expand the panel below to see the code.

Notice Embedded Javascript is used, lets us insert Javascript in the HTML editor.

We first define qty and qtyStr using our JavaScript API, getting information related to the element via the "getRowPercent() and fmtPercent() functions.

More specifically, qty is defined by the function getRowPercent, which has two arguments, the first is 'current', our current filter, and the second is which value frequency we want to show, 2 (Practice Nurse). qtyStr is defined as qty but formatted as a percent, as opposed to the decimal form. 

Where 40% is referenced in the static code above, the dynamic code uses <%=qtyStr%> instead.

Dynamic data example

<%
    let qty = table.getRowPercent('current', 2)
    let qtyStr = fmtPercent(qty)
%>

<div class="badge" style="width: 200px ; height: 200px; background-color: #39C; margin: 20px; text-align: center">
   <div class=qty style="font-size: 96px; color: white; font-weight: bold"><%=qtyStr%></div>
   <div class=label style="font-size: 16px; color: white;">Practice nurses</div>
</div>

Delete

SVG charts

Another way to add shapes to a custom chart is to use HTML tags. 

Custom chart element displaying two proportional circles side-by-side: a large blue circle labeled 'General Practitioner' with '60%', and a smaller green circle labeled 'Practice Nurse' with '40%'.

For charts that use tags set chartType to "SVGChart".

Element properties dialog for custom_chart3 displaying JSON configuration with key properties including chartType set to 'KvdChart', field set to 'S1', and chartOptions showing an empty object.

The code for custom_chart3 uses the tag to create a circle shape. Within the tag there are specified attributes. For example, r defines the radius of the circle and fill defines the circle color. More on SVG attributes.  

Expand the panel to see the code for custom_chart3.

Custom shapes example

<%
    let showMissing = getShowMissing() 
    let  marg = tabular.getMarginal(model.getKey(),'current')
    let colorKeys = Object.keys(model.get('format'))
    initColors(colorKeys)
%>

<% _.each(model.get('format'), function(label ,key) { %>
    <% var pct=marg.getPercent(key,showMissing) %>
    <% var pctStr = fmtPercent(pct)%>

    <svg height=200 width=200>
      <circle  cx=100 cy=100 r=<%=pct*100%> stroke="black" stroke-width="0" fill=<%=getColor(key)%> />
      <text x="50%" y="10%" text-anchor="middle" stroke="black" stroke-width="0.5px" ><%=label%></text>
      <text x="50%" y="50%" text-anchor="middle" stroke="black" stroke-width="0.5px" ><%=pctStr%></text>

    </svg>
    </div>
<%})%>

Delete

Static table example

The following example shows how to make a simple table and enter data manually. As always with custom charts, create a new element and set the chartType to "BasicElement". 

Protobi glossary element displaying a two-column table with 'Term' and 'Definition' headers, listing Protobi-specific terminology including autogroup, children, compact group, displayKey, element, format, global filter, key, NA values, parent, scenario, and toolbar.

To enter static data in the table, we add the "data" attribute to JSON. This attribute will take an array of objects. Each object in the array represents a different row of data. Within each object, define the columns (i.e. "Term", "Definition").

Element properties dialog for glossary showing JSON configuration with displayKey set to 'Protobi glossary', chartType as 'BasicElement', and a data array beginning with objects containing Term and Definition properties for autogroup, children, and compact group entries.

Expand the panel below to see the code to create the glossary table above.

Table example

<% var rows = model.get('data') || []%>
<% var colKeys = Object.keys(rows[0] || {}) %>
<table class="pure-table">
    <thead>
         <% _.each(colKeys, function(colKey, colIdx)  { %>
                <th><%=colKey%></th>
         <% }) %>
    </thead>
    <tbody>
        <% _.each(rows, function(row, rowIdx)  { %>
             <tr>
                 <% _.each(colKeys, function(colKey, colIdx)  { %>
                    <td> <%= _.get(row, colKey)%> </td>
                 <% }) %>
            </tr>
        <% }) %>
    </tbody>
</table>

From JSON you can add some basic CSS styling to improve the look of the HTML table. See CSS Tables for more examples.

Element properties dialog showing the continuation of glossary JSON with Term/Definition entries for 'scenario' and 'toolbar', followed by a closing bracket and 'css' object containing styling properties like 'td': { 'padding': '4px 10px', 'border-collapse': 'collapse' }.

Learn more

HTML is the code that is used to structure web content, and Lodash is a JavaScript library that helps in working with arrays, strings, objects, numbers, etc. To learn more, see the links below.

Helpful articles: