Upgrade notes for Shiny 0.14
A new Shiny release is upon us! There are many new exciting features, bug fixes, and library updates. We’ll just highlight the most important changes here, but you can browse through the full changelog below for details. This will likely be the last release before shiny 1.0, so get out your party hats!
Bookmarkable state
Shiny now supports bookmarkable state: users can save the state of an application and get a URL which will restore the application with that state. There are two types of bookmarking: encoding the state in a URL, and saving the state to the server. With an encoded state, the entire state of the application is contained in the URL’s query string. You can see this in action with this app: https://gallery.shinyapps.io/113-bookmarking-url/. An example of a bookmark URL for this app is https://gallery.shinyapps.io/113-bookmarking-url/?_inputs_&n=200. When the state is saved to the server, the URL might look something like: https://gallery.shinyapps.io/bookmark-saved/?_state_id_=d80625dc681e913a (note that this URL is not for an active app).
Important note:
Saved-to-server bookmarking currently works with Shiny Server Open Source. Support on Shiny Server Pro, RStudio Connect, and shinyapps.io is under development and testing. However, URL-encoded bookmarking works on all hosting platforms.
See this article to get started with bookmarkable state. There is also an advanced-level article (for apps that have a complex state), and a modules article that details how to use bookmarking in conjunction with modules.
Notifications
Shiny can now display notifications on the client browser by using the showNotification()
function. Use this demo app to play around with the notification API. Here’s a screenshot of a very simple notification (shown when the button is clicked):
Here’s our article about it, and the reference documentation.
Progress indicators
If your Shiny app contains computations that take a long time to complete, a progress bar can improve the user experience by communicating how far along the computation is, and how much is left. Progress bars were added in Shiny 0.10.2. In Shiny 0.14, they were changed to use the notifications system, which gives them a different look.
Important note:
If you were already using progress bars and had customized them with your own CSS, you can add the
style = "old"
argument to yourwithProgress()
call (orProgress$new()
). This will result in the same appearance as before. You can also callshinyOptions(progress.style = "old")
in your app’s server function to make all progress indicators use the old styling.
To see new progress bars in action, see this app in the gallery. You can also learn more about this in our article and in the reference documentation (either for the easier withProgress
functional API or the more complicated, but more powerful, Progress
object-oriented API.
Reconnection
Shiny can now automatically reconnect to your Shiny session if you temporarily lose network access.
Modal windows
Shiny has now built-in support for displaying modal dialogs like the one below (live app here):
To learn more about this, read our article and the reference documentation.
insertUI
and removeUI
Sometimes in a Shiny app, arbitrary HTML UI may need to be created on-the-fly in response to user input. The existing uiOutput
and renderUI
functions let you continue using reactive logic to call UI functions and make the results appear in a predetermined place in the UI. The insertUI
and removeUI
functions, which are used in the server code, allow you to use imperative logic to add and remove arbitrary chunks of HTML (all independent from one another), as many times as you want, whenever you want, wherever you want. This option may be more convenient when you want to, for example, add a new model to your app each time the user selects a different option (and leave previous models unchanged, rather than substitute the previous one for the latest one).
See this simple demo app of how one could use insertUI
and removeUI
to insert and remove text elements using a queue. Also see this other app that demonstrates how to insert and remove a few common Shiny input objects. Finally, this app shows how to dynamically insert modules using insertUI
.
For more, read our article about dynamic UI generation and the reference documentation about insertUI
and removeUI
.
Documentation for connecting to an external database
Many Shiny users have asked about best practices for accessing external databases from their Shiny applications. Although database access has long been possible using various database connector packages in R, it can be challenging to use them robustly in the dynamic environment that Shiny provides. So far, it has been mostly up to application authors to find the appropriate database drivers and to discover how to manage the database connections within an application. In order to demystify this process, we wrote a series of articles (first one here) that covers the basics of connecting to an external database, as well as some security precautions to keep in mind (e.g. how to avoid SQL injection attacks).
There are a few packages that you should look at if you’re using a relational database in a Shiny app: the dplyr
and DBI
packages (both featured in the article linked to above), and the brand new pool
package, which provides a further layer of abstraction to make it easier and safer to use either DBI
or dplyr
. pool
is not yet on CRAN. In particular, pool
will take care of managing connections, preventing memory leaks, and ensuring the best performance. See this pool
basics article and the more advanced-level article if you’re feeling adventurous! (Both of these articles contain Shiny app examples that use DBI
to connect to an external MySQL database.) If you are more comfortable with dplyr
than DBI
, don’t miss the article about the integration of pool
and dplyr
.
If you’re new to databases in the Shiny world, we recommend using dplyr
and pool
if possible. If you need greater control than dplyr
offers (for example, if you need to modify data in the database or use transactions), then use DBI
and pool
. The pool
package was introduced to make your life easier, but in no way constrains you, so we don’t envision any situation in which you’d be better off not using it. The only caveat is that pool
is not yet on CRAN, so you may prefer to wait for that.
Others
There are many more minor features, small improvements, and bug fixes than we can cover here, so we’ll just mention a few of the more noteworthy ones (the full changelog, with links to all the relevant issues and pull requests, is right below this section):
Error Sanitization: you now have the option to sanitize error messages; in other words, the content of the original error message can be suppressed so that it doesn’t leak any sensitive information. To sanitize errors everywhere in your app, just add
options(shiny.sanitize.errors = TRUE)
somewhere in your app. Read this article for more, or play with the demo app.Code Diagnostics: if there is an error parsing
ui.R
,server.R
,app.R
, orglobal.R
, Shiny will search the code for missing commas, extra commas, and unmatched braces, parens, and brackets, and will print out messages pointing out those problems. (#1126)Reactlog visualization: by default, the
showReactLog()
function (which brings up the reactive graph) also displays the time that each reactive and observer were active for:This new feature can be turned off with
showReactLog(time = FALSE)
. This may be convenient if you have a large graph and don’t want to have this new information cluttering it up. The elapsed time info shows up above each relevant node’s label, and the time is also coded by color: the slowest reactive will be dark red and the fastest will be light red.Additionally, to organize the graph, you can now drag any of the nodes to a specific position and leave it there.
Nicer-looking tables: we’ve made tables generated with
renderTable()
look cleaner and more modern. While this won’t break any older code, the finished look of your table will be quite a bit different, as the following image shows:For more, read our short article about this update, experiment with all the new features in this demo app, or check out the reference documentation.
Full changelog
Breaking changes
Progress indicators can now either use the new notification API, using
style = "notification"
(default), or be displayed with the previous styling, usingstyle = "old"
. You can also callshinyOptions(progress.style = "old")
in the server function to make all progress indicators use the old styling. Note that if you had customized your progress indicators with additional CSS, you’ll need to use the old style if you want your UI to look the same (#1160 and #1329).Closed #1161: Deprecated the
position
argument totabsetPanel()
since Bootstrap 3 stopped supporting this feature.The long-deprecated ability to pass a
func
argument to many of therender
functions has been removed.
New features
Added the ability to bookmark and restore application state. (main PR: #1209)
Added a new notification API. From R, there are new functions
showNotification
andhideNotification
. From JavaScript, there is a newShiny.notification
object that controls notifications. (#1141)Progress indicators now use the notification API. (#1160)
Added the ability for the client browser to reconnect to a new session on the server, by setting
session$allowReconnect(TRUE)
. This requires a version of Shiny Server that supports reconnections. (#1074)Added modal dialogs. (#1157)
Added insertUI and removeUI functions to be able to add and remove chunks of UI, standalone, and all independent of one another. (#1174 and #1189)
Improved
renderTable()
function to make the tables look prettier and also provide the user with a lot more parameters to customize their tables with. (#1129)Added support for the
pool
package (use Shiny’s timer/scheduler). (#1226)
Minor new features and improvements
Added
cancelOutput
argument toreq()
. This causes the currently executing reactive to cancel its execution, and leave its previous state alone (as opposed to clearing the output). (#1272)Display: Showcase
now displays the .js, .html and .css files in thewww
directory by default. In order to use showcase mode and not display these, include a new line in your Description file:IncludeWWW: False
. (#1185)Added an error sanitization option:
options(shiny.sanitize.errors = TRUE)
. By default, this option isFALSE
. WhenTRUE
, normal errors will be sanitized, displaying only a generic error message. This changes the look of an app when errors are printed (but the console log remains the same). (#1156)Added the option of passing arguments to an
xxxOutput()
function through the correspondingrenderXXX()
function via anoutputArgs
parameter to the latter. This is only valid for snippets of Shiny code in an interactiveruntime: shiny
Rmd document (never for full apps, even if embedded in an Rmd). (#1443)Added
updateActionButton()
function, so the user can change anactionButton
’s (oractionLink
’s) label and/or icon. It also checks that the icon argument (for both creation and updating of a button) is valid and throws a warning otherwise. (#1134)Added code diagnostics: if there is an error parsing ui.R, server.R, app.R, or global.R, Shiny will search the code for missing commas, extra commas, and unmatched braces, parens, and brackets, and will print out messages pointing out those problems. (#1126)
Added support for horizontal dividers in
navbarMenu
. (#1147)Added
placeholder
option topasswordInput
. (#1152)Added
session$resetBrush(brushId)
(R) andShiny.resetBrush(brushId)
(JS) to programatically clear brushes fromimageOutput
/plotOutput
. (#1197)Added textAreaInput. (thanks, @nuno-agostinho! #1300)
Added
session$sendBinaryMessage(type, message)
method for sending custom binary data to the client. See?session
. (thanks, @daef! #1316 and #1320)Almost all code examples now have a runnable example with
shinyApp()
, so that users can run the examples and see them in action. (#1158)When resized, plots are drawn with
replayPlot()
, instead of re-executing all plotting code. This results in faster plot rendering. (#1112)Exported the
isTruthy()
function. (part of PR #1272)Reactive log now shows elapsed time for reactives and observers. (#1132)
Nodes in the reactlog visualization are now sticky if the user drags them. (#1283)
Bug fixes
Fixed #1350: Highlighting of reactives didn’t work in showcase mode.
Fixed #1331:
renderPlot()
now correctly records and replays plots whenexecOnResize = FALSE
.updateDateInput()
andupdateDateRangeInput()
can now clear the date input fields. (thanks, @gaborcsardi! #1299, #1315 and #1317)Fixed #561: DataTables previously might pop up a warning when the data was updated extremely frequently.
Fixed #776: In some browsers, plots sometimes flickered when updated.
Fixed #543 and #855: When
navbarPage()
had anavbarMenu()
as the first item, it did not automatically select an item.Fixed #970:
navbarPage()
previously did not have an option to set the selected tab.Fixed #1253: Memory could leak when an observer was destroyed without first being invalidated.
Fixed #931: Nested observers could leak memory.
Fixed #1144:
updateRadioButton()
andupdateCheckboxGroupInput()
broke controls when used in modules (thanks, @sipemu!).Fixed #1093:
updateRadioButtons()
andupdateCheckboxGroupInput()
didn’t work ifchoices
was numeric vector.Fixed #1122:
downloadHandler()
popped up empty browser window if the file wasn’t present. It now gives a 404 error code.Fixed #1278: Reactive system was being flushed too often (usually this just means a more-expensive no-op than necessary).
Fixed #803 and #1179: handling malformed dates in
dateInput
andupdateDateInput()
.Fixed #1257:
updateSelectInput()
didn’t work correctly in IE 11 and Edge.Fixed #971:
runApp()
would give confusing error ifport
was not numeric.Shiny now avoids using ports that Chrome deems unsafe. (#1222)
Added workaround for quartz graphics device resolution bug, where resolution is hard-coded to 72 ppi.
Library updates
Updated to ion.RangeSlider 2.1.2.
Updated to Font Awesome 4.6.3.
Updated to Bootstrap 3.3.7.