diff --git a/R/input-submit.R b/R/input-submit.R index a5461a1ead..e26dd283ae 100644 --- a/R/input-submit.R +++ b/R/input-submit.R @@ -1,8 +1,27 @@ #' Create a submit button #' -#' Create a submit button for an input form. Forms that include a submit +#' Create a submit button for an app. Apps that include a submit #' button do not automatically update their outputs when inputs change, #' rather they wait until the user explicitly clicks the submit button. +#' The use of \code{submitButton} is generally discouraged in favor of +#' the more versatile \code{\link{actionButton}} (see details below). +#' +#' Submit buttons are unusual Shiny inputs, and we recommend using +#' \code{\link{actionButton}} instead of \code{submitButton} when you +#' want to delay a reaction. +#' See \href{http://shiny.rstudio.com/articles/action-buttons.html}{this +#' article} for more information (including a demo of how to "translate" +#' code using a \code{submitButton} to code using an \code{actionButton}). +#' +#' In essence, the presence of a submit button stops all inputs from +#' sending their values automatically to the server. This means, for +#' instance, that if there are \emph{two} submit buttons in the same app, +#' clicking either one will cause all inputs in the app to send their +#' values to the server. This is probably not what you'd want, which is +#' why submit button are unwieldy for all but the simplest apps. There +#' are other problems with submit buttons: for example, dynamically +#' created submit buttons (for example, with \code{\link{renderUI}} +#' or \code{\link{insertUI}}) will not work. #' #' @param text Button caption #' @param icon Optional \code{\link{icon}} to appear on the button @@ -13,8 +32,26 @@ #' @family input elements #' #' @examples -#' submitButton("Update View") -#' submitButton("Update View", icon("refresh")) +#' if (interactive()) { +#' +#' shinyApp( +#' ui = basicPage( +#' numericInput("num", label = "Make changes", value = 1), +#' submitButton("Update View", icon("refresh")), +#' helpText("When you click the button above, you should see", +#' "the output below update to reflect the value you", +#' "entered at the top:"), +#' verbatimTextOutput("value") +#' ), +#' server = function(input, output) { +#' +#' # submit buttons do not have a value of their own, +#' # they control when the app accesses values of other widgets. +#' # input$num is the value of the number widget. +#' output$value <- renderPrint({ input$num }) +#' } +#' ) +#' } #' @export submitButton <- function(text = "Apply Changes", icon = NULL, width = NULL) { div( diff --git a/inst/examples/07_widgets/Readme.md b/inst/examples/07_widgets/Readme.md index 7175f2bf07..25a4ad02cd 100644 --- a/inst/examples/07_widgets/Readme.md +++ b/inst/examples/07_widgets/Readme.md @@ -1 +1 @@ -This example demonstrates some additional widgets included in Shiny, such as `helpText` and `submitButton`. The latter is used to delay rendering output until the user explicitly requests it. +This example demonstrates some additional widgets included in Shiny, such as `helpText` and `actionButton`. The latter is used to delay rendering output until the user explicitly requests it (a construct which also introduces two important server functions, `eventReactive` and `isolate`). diff --git a/inst/examples/07_widgets/server.R b/inst/examples/07_widgets/server.R index f3d7f7a309..238b5bc33e 100644 --- a/inst/examples/07_widgets/server.R +++ b/inst/examples/07_widgets/server.R @@ -1,26 +1,32 @@ library(shiny) library(datasets) -# Define server logic required to summarize and view the +# Define server logic required to summarize and view the # selected dataset function(input, output) { - - # Return the requested dataset - datasetInput <- reactive({ + + # Return the requested dataset. Note that we use `eventReactive()` + # here, which takes a dependency on input$update (the action + # button), so that the output is only updated when the user + # clicks the button. + datasetInput <- eventReactive(input$update, { switch(input$dataset, "rock" = rock, "pressure" = pressure, "cars" = cars) - }) - + }, ignoreNULL = FALSE) + # Generate a summary of the dataset output$summary <- renderPrint({ dataset <- datasetInput() summary(dataset) }) - - # Show the first "n" observations + + # Show the first "n" observations. The use of `isolate()` here + # is necessary because we don't want the table to update + # whenever input$obs changes (only when the user clicks the + # action button). output$view <- renderTable({ - head(datasetInput(), n = input$obs) + head(datasetInput(), n = isolate(input$obs)) }) } diff --git a/inst/examples/07_widgets/ui.R b/inst/examples/07_widgets/ui.R index 5e5083869f..be59cf1936 100644 --- a/inst/examples/07_widgets/ui.R +++ b/inst/examples/07_widgets/ui.R @@ -2,32 +2,32 @@ library(shiny) # Define UI for dataset viewer application fluidPage( - + # Application title. titlePanel("More Widgets"), - + # Sidebar with controls to select a dataset and specify the # number of observations to view. The helpText function is # also used to include clarifying text. Most notably, the - # inclusion of a submitButton defers the rendering of output + # inclusion of an actionButton defers the rendering of output # until the user explicitly clicks the button (rather than # doing it immediately when inputs change). This is useful if # the computations required to render output are inordinately # time-consuming. sidebarLayout( sidebarPanel( - selectInput("dataset", "Choose a dataset:", + selectInput("dataset", "Choose a dataset:", choices = c("rock", "pressure", "cars")), - + numericInput("obs", "Number of observations to view:", 10), - + helpText("Note: while the data view will show only the specified", "number of observations, the summary will still be based", "on the full dataset."), - - submitButton("Update View") + + actionButton("update", "Update View") ), - + # Show a summary of the dataset and an HTML table with the # requested number of observations. Note the use of the h4 # function to provide an additional header above each output @@ -35,7 +35,7 @@ fluidPage( mainPanel( h4("Summary"), verbatimTextOutput("summary"), - + h4("Observations"), tableOutput("view") ) diff --git a/man/submitButton.Rd b/man/submitButton.Rd index 6ce82aa9c9..9aeb5feb59 100644 --- a/man/submitButton.Rd +++ b/man/submitButton.Rd @@ -18,13 +18,51 @@ see \code{\link{validateCssUnit}}.} A submit button that can be added to a UI definition. } \description{ -Create a submit button for an input form. Forms that include a submit +Create a submit button for an app. Apps that include a submit button do not automatically update their outputs when inputs change, rather they wait until the user explicitly clicks the submit button. +The use of \code{submitButton} is generally discouraged in favor of +the more versatile \code{\link{actionButton}} (see details below). +} +\details{ +Submit buttons are unusual Shiny inputs, and we recommend using +\code{\link{actionButton}} instead of \code{submitButton} when you +want to delay a reaction. +See \href{http://shiny.rstudio.com/articles/action-buttons.html}{this +article} for more information (including a demo of how to "translate" +code using a \code{submitButton} to code using an \code{actionButton}). + +In essence, the presence of a submit button stops all inputs from +sending their values automatically to the server. This means, for +instance, that if there are \emph{two} submit buttons in the same app, +clicking either one will cause all inputs in the app to send their +values to the server. This is probably not what you'd want, which is +why submit button are unwieldy for all but the simplest apps. There +are other problems with submit buttons: for example, dynamically +created submit buttons (for example, with \code{\link{renderUI}} +or \code{\link{insertUI}}) will not work. } \examples{ -submitButton("Update View") -submitButton("Update View", icon("refresh")) +if (interactive()) { + +shinyApp( + ui = basicPage( + numericInput("num", label = "Make changes", value = 1), + submitButton("Update View", icon("refresh")), + helpText("When you click the button above, you should see", + "the output below update to reflect the value you", + "entered at the top:"), + verbatimTextOutput("value") + ), + server = function(input, output) { + + # submit buttons do not have a value of their own, + # they control when the app accesses values of other widgets. + # input$num is the value of the number widget. + output$value <- renderPrint({ input$num }) + } +) +} } \seealso{ Other input.elements: \code{\link{actionButton}},