I've got a shiny
tab where the user can select several parameters via selectInput
. After the selection, the user clicks on an actionButton
and a bunch of calculations happen on the server side. Depending on both the results and the selections, one or several conditionalPanels
are supposed to be shown. The problem is that once the user changes the selection, the displayed conditionalPanel
changes immediately. However, I'd like the conditions only to be evaluated after the user has pushed the actionButton
again and the calculations on the server side have been updated. Is there a way to tie the condition of the conditionalPanel
on an actionButton
?
Here is the best MWE I could come up with to capture all the nuances (actually, the dependency of the conditional panels on some server results is still missing here):
library(shiny)
library(plyr)
ui <- fluidPage(
selectInput("variable", "Variable:",
c("SLength" = "Sepal.Length",
"SWidth" = "Sepal.Width",
"PLength" = "Petal.Length",
"PWidth" = "Petal.Width",
"Species" = "Species"),
multiple = TRUE),
br(),
actionButton("goButton", "Go!"),
hr(),
conditionalPanel(condition = "input['variable'].length == 1",
plotOutput("oneplot")),
conditionalPanel(condition = "input['variable'].length == 2",
plotOutput("twoplot"))
)
server <- function(input, output){
v <- reactiveValues(plot.type = NULL)
observeEvent(input$goButton, {
if (is.null(input$variable)) return(NULL)
if ("Species" %in% input$variable & length(input$variable > 1)){
sec.var <- input$variable[which(input$variable != "Species")]
v$summary <- ldply(by(iris[,sec.var], iris$Species, mean))
v$summary[,1] <- as.factor(v$summary[,1])
} else if ("Species" %in% input$variable)
v$summary <- table(iris$Species) else
v$summary <- iris[,input$variable]
})
output$oneplot <- renderPlot({
if (is.null(v$summary)) return(NULL)
if (input$variable == "Species") return(NULL)
hist(v$summary)
})
output$twoplot <- renderPlot({
if (is.null(v$summary)) return(NULL)
plot(v$summary)
})
}
shinyApp(ui, server)
So let's say I start the app and select SLength
and SWidth
, click the Go
-Button and get a dotplot. Then I'd want to show SLength
vs. PLength
, so I delete SWidth
from the selection field and the same moment I get two histograms, one for each of the previous selections. The conditional panel immediately reacts to the change of input$variable
, while the observer within the server script is still waiting for me to push the button. Obviously, that's not the behaviour the user would expect. The expected behaviour would be that the evaluation of the conditions of the conditional panels only happens upon pushing the Go
-button. Is there a way to achieve this?
How about doing condition on server side?
library(shiny)
library(plyr)
ui <- fluidPage(
selectInput("variable", "Variable:",
c("SLength" = "Sepal.Length",
"SWidth" = "Sepal.Width",
"PLength" = "Petal.Length",
"PWidth" = "Petal.Width",
"Species" = "Species"),
multiple = TRUE),
br(),
actionButton("goButton", "Go!"),
hr(),
plotOutput("oneplot")
# conditionalPanel(condition = "input['variable'].length == 1",
# plotOutput("oneplot")),
# conditionalPanel(condition = "input['variable'].length == 2",
# plotOutput("twoplot"))
)
server <- function(input, output){
v <- reactiveValues(plot.type = NULL)
observeEvent(input$goButton, {
if (is.null(input$variable)) return(NULL)
if ("Species" %in% input$variable & length(input$variable > 1)){
sec.var <- input$variable[which(input$variable != "Species")]
v$summary <- ldply(by(iris[,sec.var], iris$Species, mean))
v$summary[,1] <- as.factor(v$summary[,1])
} else if ("Species" %in% input$variable)
v$summary <- table(iris$Species) else
v$summary <- iris[,input$variable]
})
output$oneplot <- renderPlot({
#Added actionButton dependency here
input$goButton
isolate({
if(length(input$variable)== 1) {
if (is.null(v$summary)) return(NULL)
if (input$variable == "Species") return(NULL)
hist(v$summary)
}
else {
if (is.null(v$summary)) return(NULL)
plot(v$summary)
}
})
})
#output$twoplot <- renderPlot({
#if (is.null(v$summary)) return(NULL)
#plot(v$summary)
#})
}
shinyApp(ui, server)
EDIT: Added another option by using submitButton
You can also use submitButton()
and attach observeEvent()
to input$variable()
. "Forms 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." submitButton
library(shiny)
library(plyr)
ui <- fluidPage(
selectInput("variable", "Variable:",
c("SLength" = "Sepal.Length",
"SWidth" = "Sepal.Width",
"PLength" = "Petal.Length",
"PWidth" = "Petal.Width",
"Species" = "Species"),
multiple = TRUE),
br(),
submitButton("Go!"),
hr(),
conditionalPanel(condition = "input['variable'].length == 1",
plotOutput("oneplot")),
conditionalPanel(condition = "input['variable'].length == 2",
plotOutput("twoplot"))
)
server <- function(input, output){
v <- reactiveValues(plot.type = NULL)
observeEvent(input$variable, {
if (is.null(input$variable)) return(NULL)
if ("Species" %in% input$variable & length(input$variable > 1)){
sec.var <- input$variable[which(input$variable != "Species")]
v$summary <- ldply(by(iris[,sec.var], iris$Species, mean))
v$summary[,1] <- as.factor(v$summary[,1])
} else if ("Species" %in% input$variable)
v$summary <- table(iris$Species) else
v$summary <- iris[,input$variable]
})
output$oneplot <- renderPlot({
if (is.null(v$summary)) return(NULL)
if (input$variable == "Species") return(NULL)
hist(v$summary)
})
output$twoplot <- renderPlot({
if (is.null(v$summary)) return(NULL)
plot(v$summary)
})
}
shinyApp(ui, server)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.