Chapter 15 Custom Inputs

Shiny comes with a variety of inputs ranging from buttons to text fields; these inputs send data from the client to the R server. Custom inputs are in fact, no different than from Shiny’s out-of-the-box inputs, they work in the same way and are built on the same system.

To explain and demonstrate how to build such a custom input, we shall build a switch input, which is essentially a fancy-looking checkbox that can be toggled on and off.

Custom Shiny inputs very much resemble Shiny outputs though they consist of a single R function (e.g.: selectInput), which generates the HTML and attaches necessary dependencies. When run from the R console, such functions will reveal the HTML they generate.

The R function is paired with a JavaScript input binding akin to the output binding used in the previous chapter.

15.1 Setup

Let us set up the necessary files and project structure. Below an asset directory is created. In it, we place a JavaScript file where the binding will be coded, as well as a CSS file that will style the switch input, an app.R file is also created to hold the R code and application.

This should create the following directory structure.

.
├── app.R
└── assets
    ├── binding.js
    └── styles.css

15.3 Generate Input HTML

Let us start with the R function to be used in the Shiny UI. The <input> it generates bears a switchInput class, which will be used to identify all switch inputs from JavaScript. This was also done in the custom output. The function accepts an id argument; this is also common across all inputs and outputs as a unique identifier is required in order to retrieve the input JavaScript-side.

The function should also accept a customary label and a checked argument to define the initial state of the switch.

As for the custom outputs, the dependencies (CSS and JavaScript binding) can piggy back on the generated HTML.

15.4 JavaScript Input Binding

The JavaScript input binding is instantiated from Shiny.InputBinding, this is similar to output bindings which are instantiated from Shiny.OutputBinding.

Then again the binding is “extended.” This consists of adding several methods.

  • find returns all the relevant inputs.
  • getId returns the unique identifier of the input.
  • getValue returns the value of the input to be sent to the server.
  • setValue is used to set the value of the input.
  • receiveMessage is used to receive messages from the server.
  • subscribe tells Shiny when and how to send the updated input value to the server.
  • unsubscribe removes event handlers and stops Shiny from sending updated values to the server.

15.4.1 Find Inputs

The find method looks for all the relevant HTML elements in the document (scope) and returns them as an array. Many other methods we are about to implement will accept el as an argument; this will ultimately be one of the elements returned by find.

Generally, the find method is used in conjunction with a class; hence the <input> generated by switchInput bears a class of the same name switchInput.

15.4.2 Get Input Id

The getId method is exactly what it appears to be; it returns the id of the element. It looks for that id as data-input-id attribute, and if that is not found returns the id; this can be observed in the source code (below).

Since the default works, there is no need to use it for the switch input.

15.4.3 Get Input Value

That retrieves the value of the input; this is often the attribute of the same name (value="something"), which can be obtained with the jQuery val() method. The switch is an input of type checkbox and therefore uses the checked prop.

The value of the checked prop is boolean, true if checked and false if unchecked.

Ensure the getValue method actually returns the value.

15.4.4 Set Input Value

The setValue method sets the value of the input; hence it also accepts the value object: the actual value to which the input should be set. Then again, most inputs will likely use the value attribute, which can be set in jQuery with val(newValue), but the checkbox uses the checked prop.

Note the use of the change method, which ensures the event is fired. Otherwise the input is checked or unchecked, but the change event is not fired, and this will cause problems later on as we rely on this event.

15.4.5 Receive Input Messages

The setValue method previously defined is only beneficial when combined with receiveMessage; the latter handles messages sent to the input, and these are generally sent from the server via functions the likes of updateSelectInput. Internally it uses the setValue method to define the value of the input received from the server. Note that the value is, therefore, a serialised JSON input coming from the R server and can be of any complexity you desire. Below we use it such that it expects a simple boolean as the checkbox (switch) can be either on (true) or off (false).

15.4.6 Subscribe and Unsubscribe Inputs

Finally, a crucial method is subscribe. This is run when the input is registered (more on that later) and is used to determine when Shiny sends new values of the input back to the server. This method also accepts a callback, which is the same function that tells Shiny to update the value. This callback function accepts a single boolean value, which the source code states is used to enable debouncing or throttling. This is covered in the next section on rate policy.

This method often consists of an event listener that observes changes on the input to send it to the server. In layman terms, when the switch input changes (on to off or vice versa) run the callback function, which sends the data to the server.

Note that in the subscribe method we listen for changes on the input; hence the setValue also uses jQuery’s change method; it ensures this event is fired and that Shiny will subsequently pick it up.

Make sure the setValue method triggers the event observed in subscribe

15.4.7 Input Rate Policy

The rate policy determines how frequently the binding should send new input values back to the server. The getRatePolicy method should return an object that describes a JSON array with two variables: policy and delay.

direct

The direct policy tells Shiny to sends any new value directly, however often this occurs. Therefore, this policy does not make use of delay.

debounce

The debounce policy tells Shiny to ignore all new values until no new values have been received for delay milliseconds.

throttle

The throttle policy means that no more than one value will be sent per delay milliseconds.

A switch input is not expected to change frequently, but it’s nonetheless good practice to throttle it to ensure the server does not receive too many requests. This will admittedly be more relevant to inputs that see a higher rate of change like text fields, which unless debounced send every keystroke to the server.

15.5 Update Input

The JavaScript binding was provided with the required methods to receive updates from the server to change the value of the switch input, but the R function that sends those updates is yet to be written.

This pattern was used previously, albeit using sendCustomMessage; with sendInputMessage the message can be sent straight to the receiveMessage handler of the input using 1) the id of the input and 2) the data one wants to send.

We can adapt the application to use this button.

Figure 15.3 attempts to summarize the various elements that were put together and used in the last application.

It all starts from the switchInput function, which generates the HTML defining the switch input and its initial state. In the subscribe method, an event listener checks for changes on this HTML element ($(el).on('change', ...)). Every time it changes (check/uncheck) it fires the Shiny callback, which sends the value of the input obtained from getValue through the WebSocket. When the value of the input is changed from the server this value travels through the WebSocket to the front end, where receiveMessage uses setValue to programmatically change the check-box, which incidentally triggers the change event, and back we go.

FIGURE 15.3: Shiny input visualised

15.6 Exercise

  • Add a toggle_switch_input function that toggles between states so it turns it off when it’s on and vice versa
  • Bring support for Bootstrap 3 text input addon