How to build a JavaScript based widget


A key feature of shiny is that users can create powerful apps driven by R without having to know HTML, CSS, or JavaScript. However, incorporating these technologies into your apps can greatly enhance the power of shiny.

Furthermore, in recent years there has been a shift from using base R graphics to using interactive JavaScript web components for data analysis and data visualization. In order to use the functionality offered in these frameworks, we have to construct R bindings to JavaScript libraries.

The htmlwidgets package provides a framework for creating such bindings and allows you to bring the best of JavaScript into R using a set of easy-to-follow conventions. After a widget has been constructed, embedding it into a shiny app or R Markdown document only takes a few lines of code. For some examples on what htmlwidgets can do, take a look at the showcase on the htmlwidgets website.

Even though using an htmlwidget is easy, constructing one may be challenging at first as you have to know a number of concepts in order to create a widget. These include things such as how to build an R package and how to use some basic JavaScript, CSS and HTML. However, you don’t need to be an expert in these things to create quite useful new functionality.

The tutorials below are intended for the intermediate shiny enthusiast with limited experience in HTML, CSS and/or JavaScript, who wants to learn how to extend shiny. A useful first step in this process is to be able to create your own htmlwidgets.

Creating a dashboard app

The widgets we are going to build are all based on c3.js, which in turn is built on the more extensive JavaScript visualization library d3.js. C3.js provides a variety of chart types, such as gauges, pie charts, stacked bar charts, stacked area charts and charts to display time series. Furthermore, c3.js provides a variety of APIs and callbacks to access and update the state of a chart after it’s rendered.

In order to master the technique of creating widgets, we will construct an interactive dashboard application which includes a variety of htmlwidgets based on c3.js. A screenshot of the end result can be seen below. A live version of a more complete version of our dashboard can be seen here (this app is best viewed on a high res screen).

the end result of the tutorials

During the tutorials that follow, we will gradually build more complex widgets with more functionality. The end result will be a fully functional dashboard. An advantage of using JavaScript over base R graphics is that we have access to various types of events e.g. hover, click and drag events. For instance, the dashboard will have a nice brush-able timeline component.

a brush-able timeline which acts as a data filter

The timeline acts as a time based filter for all of the data in the other charts. In the tutorials, we will take a deeper look into the notion of sending data from the client to the server and back using shiny. This functionality will be based mainly around three pivotal functions: the JavaScript functions Shiny.onInputChange, Shiny.addCustomMessageHandler and the R Shiny function sendCustomMessage. A great introduction to these functions is offered in this blog post, and we will discuss each function in detail within the tutorials as well.

Dashboard data

The data in the dashboard represents data from an insurance company that screens persons who apply for a new insurance during underwriting. Underwriting is the process in which an insurance company assesses whether or not it should accept a person into their portfolio. If the risk for specific type of claims is deemed too high, the insurer may decide to reject an application. For the purposes of the tutorials, we use a toy dataset of 20,000 rows which looks like this:

  id       date score result    branch   product    process    label
1  1 2014-04-10     0  GREEN Generated Property      Claims    Phone
2  2 2015-10-22    60  AMBER Generated Property     New car    Phone
3  3 2015-11-10   150    RED    Damage Property  Acceptance Internet
4  4 2015-11-06    25  GREEN    Damage Liability     Claims    Phone
5  5 2014-09-29    10  GREEN    Damage      Pets Acceptance Internet
6  6 2014-01-28     5  GREEN    Damage Property  New driver   Agency

Each row represents a new screening. The column id provides a unique case, while the column date indicates the date at which a person was screened. The column score indicates the risk score estimated by the insurance company. Higher scores indicate that the person has a higher estimated probability to file a claim or to commit fraud somewhere in the future. The column result refers to a discretized version of the score column. For our dashboard this is the most important variable. Scores between 0 and 50 are mapped to GREEN, while scores from 51 to 75 are mapped to AMBER. Scores above 100 are mapped to RED, which indicates the highest risk group. The final four columns indicate the branch, product, process, and label associated with the policy application. The exact meaning of these categories depends on the insurer. Their main purpose is to help the insurer to process new policy applications more quickly.

In the screenshot above, the four gauges indicate the percentage of RED cases for a specific time period. You can select the percentages for different risk groups with the drop-down menu on the left. The four pie charts indicate the distribution of the screenings over the various processes, labels, product and branches. The bar + line chart is an example of a c3.js combination chart with dual y-axes and a single x-axis indicating time. The gray bars indicate the total number of screenings for each week (left y-axis), while the green, amber and red lines correspond to the percentage of cases which are estimated as GREEN, AMBER or RED, respectively (right y-axis). Finally, the bottom chart shows the same information, but this time as a stacked area chart. The toggle button on the left allows you to toggle between displaying percentages or absolute counts.

For each chart type, we’ll create a separate htmlwidget. For the toggle button, we’ll make a shiny input binding (see below).

Creating a dynamic help system

In addition to teaching you how to create widgets, the tutorials will teach you how to create an interactive, dynamic help system, complete with animated transitions. The help system is based on another JavaScript library, intro.js. This library allows you to create a step-by-step guide for a website. It will draw a nice box around elements of your choice, combined with an annotation layer and a navigation system. Here’s an example of how the help will look for one of the gauges in the dashboard.