Reputation: 1431
The idea
Depending on selectizeInput()
input I want to display one row of data from a data frame. However, some variables are only to be displayed if their value is not FALSE
. selectizeInput()
includes a placeholder prompt, which is highly desirable.
The problem
The code I developed actually works but until any option is selected displays
Error in if: argument is of length zero
inside the app, which is highly undesirable.
Example code
library("shiny")
# simulate data
data <- data.frame(
name = c("Adam", "Debbie", "Lancelot", "Dracula"),
age = c(21, 48, 72, 1023),
coward = c("yes, a coward", "just a little bit", FALSE, "too old to be a coward")
)
ui <- fluidPage(
# selectize
selectizeInput(
inputId = "input",
label = NULL,
choices = c("..." = "", as.character(data[, "name"])),
selected = NULL,
multiple = FALSE
),
# show output
uiOutput(outputId = "output")
)
server <- function(input, output, session){
output$output <- renderUI({
div(
# show name
data[which(input$input == data[, "name"]), "name"], br(),
data[which(input$input == data[, "name"]), "age"], br(),
# if "coward" is not FALSE than show its value
if(data[which(input$input == data[, "name"]), "coward"] != FALSE){
data[which(input$input == data[, "name"]), "coward"]
}
)
})
}
shinyApp(ui, server)
Attempted solutions
Tried wrapping if()
statement in suppressWarnings()
or suppressMessages()
. Does not change anything. Also tried putting !is.null(input$input) &&
inside if()
condition but it just changes the initial error to
Error: missing value where TRUE/FALSE needed
The question
How to write the condition so that shiny
would not return an error before selecting an option in selectizeInput()
?
Any other, more general hack to force shiny
not to display error messages inside the app?
I feel I`m missing something obvious here...
Upvotes: 4
Views: 12803
Reputation: 1431
The answer including browser()
function was indeed helpful for locating the source of the problem but the real solution is to use req()
or a combination of validate()
and need()
functions. See respective help()
pages to learn how to use them.
In short what these functions do is to check whether the argument given has been specified. In reference to the example code the solution could look like this:
server <- function(input, output, session){
output$output <- renderUI({
# check if input$input is specified
# if not stop executing the rest of this code block
req(input$input)
div(
# show name
data[which(input$input == data[, "name"]), "name"], br(),
data[which(input$input == data[, "name"]), "age"], br(),
# if "coward" is not FALSE than show its value
if(data[which(input$input == data[, "name"]), "coward"] != FALSE){
data[which(input$input == data[, "name"]), "coward"]
}
)
})
}
Upvotes: 8
Reputation: 26313
Whenever you get an error you're not sure about in R, the first thing to do is to try to isolate it and use browser()
to see what happens just before the error. After doing this, I found out the error has nothing to do with shiny or the UI, it's just because you're trying to compare a factor(0)
to FALSE
.
The value of input$input
is initially ""
. This means the value of data[which(input$input == data[, "name"]), "coward"]
is initially factor(0)
. Which means your if statement is doing a factor(0) == FALSE
comparison, which breaks.
To figure that out all I needed to do was simplify the server code to
server <- function(input, output, session){
observe({
mydata <- data[which(input$input == data[, "name"]), "coward"]
browser()
if (mydata == FALSE) {
cat("hello")
}
})
}
And using the debugger I saw what values are being used
Upvotes: 8
Reputation: 23101
A hack that works:
server <- function(input, output, session){
output$output <- renderUI({
div(
# show name
data[which(input$input == data[, "name"]), "name"], br(),
data[which(input$input == data[, "name"]), "age"], br(),
# if "coward" is not FALSE than show its value
if((length(input$input) > 1) &&
(data[which(input$input == data[, "name"]), "coward"] != FALSE)){
data[which(input$input == data[, "name"]), "coward"]
}
)
})
}
Upvotes: 0