Why you should learn Javascript to master R Shiny. And how to get started


Shiny and JavaScript

Shiny has become the status quo of building web apps/dashboards with R . A major reason of its success is that you don't need to know javascript to create basic interactive web apps.

Although the concealment of this important feature is by design and makes Shiny in the first instance easy to use, in the long run when you want to build serious and more visual appealing apps, you most likely need to utilize javascript to make most of the web framework.    

Learning javascript doesn’t only benefit your shiny apps, the new acquired skill set can be applied in other R web frameworks such as OpenCPU or even use it outside the Shiny spectrum. In fact, javascript is the lingua franca of web development, meaning you can utilize the acquired skills to create stunning user interfaces (i.e. dashboards) for various other data (backend) languages, such as python, skala, NET and so forth

 

How to Get Started With Javascript

A frequently heard argument against Javascript from Shiny users or R developers in general, is the difficulty and the time consumption of learning Javascript. Surprised to hear this coming from developers who are familiar with a language (R), considered as one of the steepest language to master. The reality is that you don't need to master javascript in depth to benefit from the language. A surficial touch, enough to let a javascript library work, would be in most cases enough.

Furthermore, there are many JS frameworks such as jQuery, a popular framework used intensively within Shiny, that hide many complexities making JS easier to use and to learn.  jQuery library is known as the ‘code less do more’ library

Moreover, even Yihui Xie (auhor of the popular Knitr package), whose first task for RStudio was to bring the JS library datatable to Shiny, admitted in a recent blog that he didn’t have JS skills when creating the package, and was frequently copying code from stackoverflow. This indicates that you don’t have to be a JS expert.

My personal experience is that you rarely need advanced JS skills to get most of a javascript library. Just like YiHui, you can use the following strategy:

 

  • If you have an idea that you want to implement in your Shiny app, search on the internet for JS libraries that can assist in achieving your goals.
  • Having found a library that suits your need, read the documentation.
  • After reading the documentation, look at the examples and use cases that are accompanied with the library. You can try to mimic and play around with the library on a playground such as JSFiddle

 

Following these 3 steps would mostly be sufficient to get started. If you need more advanced usages of the library, you can use stackoverflow to explore questions on the JS library. Also, when you get errors / issues, stackoverflow can help you to find solutions.

 

How to use Javascrpt within Shiny

Generally, there are 3 ways to get started with JavaScript in Shiny :

Method 1. Htmlwidgets: This basically lets you integrate libraries into the R environment, meaning that in theory thousands of JavaScript libraries can be used from R. There are already some in built widgets which you can use out of the box in Shiny. One of the frequently used widgets is datatable, which transforms R dataframes to intereactive  html tables. 

HtmlWidgets can be considered as a wrapper around the JS library that you want to integrate, making the communication between JS library and R easier.

Creating a htmlwidget follows the following conventions:

  1. Dependencies, these are the JavaScript libraries for which you want to write an R wrapper.
  2. R binding. This is the R function that you can call, and where you define the parameters, and how the widget is rendered.
  3. Javascript binding, a Javascript function serving as a middle layer between the R binding (R) and the Dependencies (Javascript). The data and options are gathered from the R binding and passed to the underlying dependencies.

To have a feeling of implemting an htmlwidget, you can have a look at the skeleton of the implementation of datatable at github.

Method 2. Call javascript from Shiny:

A big advantage of creating an htmlwidget is that it can be used as an R package, which can be utilized outside Shiny in other R projects as well. Disadvantage is that it takes time and debugging efforts to build htmlwidgets.

Another less time intensive way to communicate with your Javascript dependencies is calling Javascript directly from Shiny via so-called callbacks. This process entails two layers:

2a. Session$sendCustomMessage R function (sendCustomMessage) that outputs R objects to Javascript  

 

The session$sendCustomMessage(type, object)function lives in R, and contains two parameters:

    1. type, a unique name of the callback.

    2. Object, the data you want to convey.

2b. Shiny.addCustomMessageHandler. The Javascript middle layer:  

 

Shiny.addCustomMessageHandler lives in Javascript and serves as a middle layer between R and Javascript. On the one hand it ‘receives’ the R object as passed by Session$sendCustomMessage (see a), on the other hand it passes the object to the javascript dependencies that you want to utilize in your app.

 

Shiny.addCustomMessageHandler(type, JavascriptFunction), contains two parameters:

 

  1.  type, the name of the callback as defined in (a).

  2.  JavascriptFunction is the javascript function, consuming the R object.

 

Fictive Example

In R we define a data.frame “df” which is subsequently conveyed to JS  for each slider change event by using the session$sendCustomMessage function:

df <- data.frame(klm = c(1:100))
observeEvent(input$slider,
             {session$sendCustomMessage("handler1",df)}) 
}

 

In JS we consume the conveyed data.frame as follows:

Shiny.addCustomMessageHandler("handler1", hello);
function hello (message){
  alert(JSON.stringify(message));
}

So Shiny.addCustomMessagler lives in JS, passes the R object “df” to the hello JS function, which alerts the object on the screen.

Noteworthy is that communication between R and JavaScript takes place through JSON. Hence, calling JSON.stringify to convert data.frame object as json to a string object.

 

Method 3. Send an object from Javascript to Shiny

Sending messages from Shiny to Javascript is not always sufficient, sometimes you want to enable the way around by sending objects from JS to Shiny. This entails the following two steps:

3a) Shiny.onInputChange(id, object) lives in JS and conveys JS objects to R, and contains two parameters:

  1.  Id = the unique id of the JS object you want to convey to R.
  2. Object = JS object to be conveyed to R.

 

3b) Read in R ,the JS object by referencing the unique id as defined in 3a).

 

Fictive example:

In JS you send the following JS message object to R when an action button is hovered:   

$(document).ready(function() {
  $( "#goButton" ).hover(function(){
    var message = {id: "id1", data : [1,2], nonce: Math.random()};
    Shiny.onInputChange("GetJs", message);
  });
});      

In R you read the JS object as follows:

observeEvent(input$GetJs, cat(“JS object received”)
ENTER YOUR EMAIL TO GET FREE TUTORIALS, ARTICLES AND UPDATES ON BUILDING DATA SKILLS.