RStudio’s shiny is a great framework to generate web applications with R. In a classical shiny app, interactivity is not generated via event handlers but by reactive programming. For details, see the shiny documentation and tutorials under http://shiny.rstudio.com/.
While shiny’s reactive programming model is great for smaller apps, I personally found it less useful for bigger applications that create a lot of interactive dynamic UI.
For example, when writing the initial shiny interface for my package RTutor https://github.com/skranz/RTutor, I felt that some observers or render functions were triggered too frequently, and I was not sure where to best put the ‘server code’ of newly dynamically created objects. Of course, it is definitely possible to write large applications with reactivity, but given my limited understanding of the reactivity model, it just was hard for me…
Anyway, I generated the package shinyEvents to emulate the classical event-handling paradigm for shiny applications and find it personally quite useful…
The shinyEvents package allows to write shiny applications that use classical event handlers, e.g. for button clicks, value changes, etc. One does not write an explicit server function, but just adds event handlers to an app object. Widgets will be updated with explicit calls to updateXXX or setXXXX functions, like e.g. setText(id, "New text"). Widget values and event handlers can be set in a similar fashion for an app that has not yet started as for an already running app.
Installation
To install the package see the description on the package’s Github page:
Note that a call to eventsApp() stores the generated app object (an environment) globally. The calls to buttonHandler, changeHandler and setText reference by default to this globally stored app object. Once the app starts, a copy of the app object will be generated for each user session that is generated by shiny.
Such a simple app app could be much easier written with the standard reactivity model of shiny. Yet, shinyEvents can become more useful when you have an app that creates a lot of dynamic UI.
A simple app with dynamic UI
Here is a simple app that creates dynamic UI.
The button handler for the static button creates and sets a new UI with another button and also generates a handler for the new button.
Note:
The syntax for creating handlers (and setting values) stays the same for dynamic objects created by an already running app as for static objects that are created before the app has started.
The dynamically created button Handler
buttonHandler("dynBtn", ui.count = value, function(value,ui.count...) {
passes a manual parameter ui.count to the handler function.
A small chat app
The code below generates a small chat application as a shiny events app in which multiple users can interact. Open multiple browser windows to see how chatting among multiple clients works.
We use some new handlers in this example:
aceHotkeyHandler(...) can handle hotkeys in an aceEditor input
timerHandler(...) specifies a function that will be called in fixed time intervals
appInitHandler(...) specifies a function to customize a newly initiated session of the app
The app object has a field glob that can be used to store variables that will be shared among sessions. (Of course, you could alternatively just use a global variable directly in R.)
Deploying as a shiny app
The example run the generated app locally. Of course you can also deploy an event app via shiny server. Just generate in the usual fashion an app folder with files ui.R, server.R, and global.R.
I would recommend to ui.R and server.R to be the following one-liners:
and
The generation of the app can then be put into global.R. If our first example, we would put into global.R: