Avoiding reactivity in a Shiny app

[This article was first published on Saturn Elephant, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Sometimes the Shiny reactivity is not desirable. Assume for example the Shiny app renders a plot and the title of this plot is given by the user with a text input. So in the Shiny UI you have

textInput("title", label = "Title"),
plotOutput("ggplot")

and in the Shiny server you have

output[["ggplot"]] <- renderPlot({
  ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
    geom_point() +
    ggtitle(input[["title"]])
})

The problem is that a new rendering of the plot will occur whenever the user types a new character for the title in the text input.

One possibility to avoid this problem is to use an action button to submit the title, but this is not very convenient.

Another, more convenient possibility is to submit the title whenever the Enter key is pressed. Here is how to implement this feature. We use JavaScript to listen to the key press event and if the pressed key is the Enter key then we send a signal to the Shiny server:

js <- '
$(document).on("keyup", function(e) {
  if(e.keyCode == 13) {
    Shiny.setInputValue("keyPressed", true, {priority: "event"});
  }
});
'

The number 13 is the key code of the Enter key. When it is pressed, the line Shiny.setInputValue(...) is executed. This command sends the Shiny value input[["keyPressed"]] to the Shiny server. Its value is always TRUE. Thanks to the option priority: "event", the Shiny server will react to input[["keyPressed"]] each time it is sent, even though its value does not change.

To include this JavaScript code in the Shiny app, we have to insert tags$script(HTML(js)) in the Shiny UI.

Now, in the Shiny server we define our reactive title:

Title <- eventReactive(input[["keyPressed"]], {
  input[["title"]]
})

and then we code the rendering of the plot as follows:

output[["ggplot"]] <- renderPlot({
  ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
    geom_point() +
    ggtitle(Title())
})
To leave a comment for the author, please follow the link and comment on their blog: Saturn Elephant.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)