7 easy steps to custom inputs in shiny

This article is updated and moved to https://www.mail-wolf.de

A step by step guide on how to include custom inputs into R Shiny. This guide is going through an example of a custom input build from jQuery. After the tutorial you will be able to: Build your own front-end elements in shiny AND receive their values in R.

Why a second guide on building custom shiny inputs?

For more than two years we are developing one of the largest Shiny apps in the world. It’s large in terms of interaction items and lines of code. I already explained this in one of my former blog entries on how to write such an app. I used some techniques in Advanced R to build it.

What is important for a custom shiny input?

These are the chapters I will go through to build an app with custom shiny inputs and the things you need to know to do it yourself:

  1. Know some basic HTML and JS for the setup
  2. Know how to start with the JavaScript InputBinding file
  3. Know what your getValue function looks like
  4. Know what your subscribe function looks like
  5. Know how to handle the input
  6. Don’t build reactive stuff about you input in R, do as much as possible in JavaScript

The example

My example is pretty artificial, but there is a reason for that. I want to make it hard to get the value of the input and use jQuery, because it has a lot of really cool features and is already included in shiny . So let’s imagine you want to define two colors. One is your bar border color, the other is your bar fill color. Both shall be entered using a color picker. Upon being too close (e.g. red and dark red) there shall be a little note on this. I will do this using the Telephones by region App from the Shiny Gallery because it includes a barplot. But let’s start from scratch

1 Know how to find fancy and easy to implement inputs

The app shall get two inputs that allow you to choose colors. Such inputs are called color pickers. This tutorial will deal with jQuery inputs. JQuery is easy to learn and already included in shiny. So let’s start searching for inputs by googling the following: “colorpicker jquery” .These are my results:

Image for post
Image for post
Results for googling jQuery colorpicker
$('#colorpickerHolder').ColorPicker({flat: true});
$('input').ColorPicker(options);
<input type='text' id="custom" /><script>
$("#custom").spectrum({
color: "#f00"
});
</script>
$('input').val()

Takeaway #1: Search for jQuery based tools that provide HTML in their tutorials

2 Know some basic HTML and JS for the setup

This chapter is about the front-end setup of your custom input element. Therefore you need to know some basic HTML. First thing to know: what is a class and what is an ID. Please read this at the desired links on w3schools if you do not know the difference.

<input type='text' id="custom" /><script>
$("#custom").spectrum({
color: "#f00"
});
</script>
  • the default color
shiny::textInput(inputId = "custom")
<input type='text' id="custom" />
Image for post
Image for post
Placing the spectrum.js and spectrum.css files at the right place
<script src='spectrum.js'></script>
<link rel='stylesheet' href='spectrum.css' />
tags$head(
tags$link(rel = "stylesheet", type = "text/css",
href = "spectrum.css"),
tags$script(src="spectrum.js")
)
Image for post
Image for post
Image of custom_inputs_lessonone.R Shiny app

Takeaway #2: Try to use Shiny Input Elements inside your custom elements.

Takeaway #3: Do not forget to source the JavaScript and CSS files of your custom element.

Takeaway #4: Put a div container around your element and give it a special class.

3 Know how to start with the JavaScript InputBinding file

The first step to make your input a real custom input is creating a JavaScript file as described in the tutorial by RStudio. It has to contain three main elements.

  1. The extension of your custom InputBinding
  2. The registration of your custom InputBinding
// #1
var DoubleColorPickerBinding = new Shiny.InputBinding();
// #3
Shiny.inputBindings.register(DoubleColorPickerBinding);
  1. getValue
  2. setValue
  3. subscribe
  4. unsubscribe
find: function(scope) {
return $(scope).find(".doublecolorpicker");
}

Takeaway #5: Use the jQuery.find() function to get your element into the Shiny.InputBinding.

4 Know what your getValue function looks like

Here comes the hard part. We now want to access the value of our custom input and hand it over to R. Therefore we need to work on the getValue function inside the JavaScript file. This function basically returns the values of your custom input element into your shiny input variable.

[
{name:'border',
color:'red'},
{name:'fill',
color:'blue'}
]

Takeaway #6: Derive input element Values by jQuery.val()

Takeaway #7: Use JSON arrays to derive multiple input values

5 Know what your subscribe function looks like

Now we have a custom input using two color pickers and we are able to derive the value of this input. Next we need shiny to also react upon changes of this input. This is what is called subscribe.

$(el).on('change.selectized', function(event) {     callback(false);});

Takeaway #8: Use the jQuery.change() function to derive changes of inputs.

Takeaway #9: Try to give each element inside your custom input a desired HTML/CSS class.

6 Know how to handle the input

Now we have a custom input that allows you to read two color pickers into one JSON string. This JSON string is available inside R by a shiny input. Additionally changes on one of the two colors will do a callback to shiny and inform it, that it has to react. We are finished with our custom input? No, we want it to come out of the JavaScript interaction not as a JSON string, but as a nice and readable list like:

[["fill"]]
"#f00000"
[["border"]]
"#00000f"
  1. add the function call before your server.R is source
getType: function(el) {
return "DoubleColorPickerBinding";
}

Takeaway #10: Use registerInputHandler function to parse the response from your custom input over into something useful in R.

7 Don’t build reactive stuff about you input in R, do as much as possible in JavaScript

Actually, you are done with the application. Get the shiny Telephones by Region example and make sure your ui.R sources DoubleColorPicker.R and contains DoubleColorPickerInput("myid") inside your sidePanel . Additionally your ui.R should have

tags$head(
tags$link(rel = "stylesheet", type = "text/css", href = "spectrum.css"),
tags$script(src="spectrum.js"),
tags$script(src="DoubleColorPickerInput.js") )
color_list <- input$myid
barplot(WorldPhones[,input$region]*1000,
main=input$region,
ylab="Number of Telephones",
xlab="Year",
col = color_list[["fill"]],,
border = color_list[["border"]],
lwd=3
)
Image for post
Image for post
Final solution application
Image for post
Image for post
Warning message upon inserting two equal colors

Takeaway #11: JavaScript can save you calculation steps in your user interface

Summary

In summary I have to say that my blog post shall be named “7 steps to get custom inputs in shiny as easy as possible”. It is not easy to insert a custom input element into R-Shiny. It seems nearly impossible if you do not understand any JavaScipt. This tutorial should allow you to go through building up a new R-Shiny input by 7 steps. If you follow the 7 steps and do not forget to check one, you will succeed in building up new user interface elements. Those new elements will allow your users to insert something into your app they never thought about. We enabled things like a drag&drop input, an input to rearrange a bunch of plots on a grid, fancier check boxes, on-off switches, anything you can imagine. You can read whole books on fancy inputs or check websites like https://bootsnipp.com/ or https://freefrontend.com.

Takeaways

  1. Search for jQuery based tools that provide HTML tutorials
  2. Try to use Shiny Input Elements inside your custom elements.
  3. Do not forget to source the JavaScript and CSS files of your custom element.
  4. Put a div container around your element and give it a special class.
  5. Use the jQuery.find() function to get your element into the Shiny.InputBinding.
  6. Derive input element Values by jQuery.val()
  7. Use JSON arrays to derive multiple input values
  8. Use the jQuery.change() function to derive changes of inputs.
  9. Try to give each element inside your custom input a desired HTML class.
  10. Use registerInputHandler function to parse the response from your custom input over into something useful in R.
  11. JavaScript can save you calculation steps in your user interface

Written by

software developer, data enthusiast, traveler and biostatistician — posting to https://www.mail-wolf.de

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store