I am trying to conditionally swith shiny output render types in a flexdashboard tab using conditionalPanel
as outlined in the Shiny documentation here, by using a reactive output object and making sure it is returned to the browser by using outputOptions(output, [myOutputName], suspendWhenHidden = FALSE)
. This approach has been suggested in several SO anwsers (e.g. here and here) for full-fledged Shiny apps but I could not find an example for their use in a Shiny document (R markdown). Essentially, I want to test if a selected data set has a certain column (i.e. the column is not null
), and make the UI conditionally render the plot based upon the presence of this column. In the toy data below, the list has a known number of items, and it is known which ones have the missing column. When running the document locally, the desired behavior is there (i.e. the set will switch based upon the selection and the conditionalPanel appears to show what I would like it to show), but still the inspector shows the errors that I listed below. Publishing on rstudio connect leads to the interface just not being rendered (because of the same errors, I presume). Are these errors (Error evaluating expression: ouput.evalseplen == true
and Uncaught ReferenceError: ouput is not defined
) in the inspector a known shiny bug? Or is something deeper going on?
---
title: "fdb_reprex"
author: "FMKerchof"
runtime: shiny
output:
flexdashboard::flex_dashboard:
orientation: rows
inlcudes:
navbar:
- { title: "More info", href: "https://github.com/FMKerckhof", align: right }
fontsize: 9pt
editor_options:
chunk_output_type: console
---
```{r setup, include=FALSE}
# Set knitr options ----
knitr::opts_chunk$set(echo = TRUE)
# load packages ----
library(shiny)
library(shinydashboard)
library(ggplot2)
library(plotly)
# toy dataset ----
inputlist <- list(fulliris=iris,
irisnoseplen=iris[,-1],
irisnopetlen=iris[,c(1,2,4,5)])
```
Inputs {.sidebar}
=======================================================================
```{r datasetsel, echo = FALSE}
renderUI(inputPanel(
selectInput("datasetsel", label = "Choose your dataset:",
choices = unique(names(inputlist)),
selected = unique(names(inputlist))[2])
))
selected_data <- reactive({
inputlist[[input$datasetsel]]
}) |> bindEvent(input$datasetsel)
```
Sepals {data-icon="fa-leaf"}
=====================================
Row {.tabset}
-------------------------------------
### Sepal widths
```{r sepwidthplotly, echo=FALSE}
output$p1 <- renderPlotly({
req(selected_data())
p1 <- selected_data() |>
ggplot(aes(y=Sepal.Width,fill=Species,x=Species)) + geom_boxplot() + theme_bw()
ggplotly(p1)
})
plotlyOutput("p1", width = "auto", height = "auto")
```
### Sepal lengths
```{r seplenplotly, echo=FALSE}
output$p2 <- renderPlotly({
if(!is.null(selected_data()$Sepal.Length)){
p2 <- selected_data() |>
ggplot(aes(y=Sepal.Length,fill=Species,x=Species)) + geom_boxplot() + theme_bw()
ggplotly(p2)
}
})
output$noseplentext <- renderText({
if(is.null(selected_data()$Sepal.Length)){
"No Sepal Lengths in the selected dataset"
}
})
output$evalseplen <- reactive({
return(is.null(selected_data()$Sepal.Length))
})
outputOptions(output, "evalseplen", suspendWhenHidden = FALSE)
conditionalPanel(condition = "ouput.evalseplen == true",
textOutput("noseplentext"))
conditionalPanel(condition = "ouput.evalseplen == false",
plotlyOutput("p2",width="auto",height="auto"))
```
From the inspector it becomes clear that the output is not defined, but I explicitly asked for it to be returned by setting suspendWhenHidden
to FALSE
My session information: R 4.1.2, shiny 1.7.1, flexdashboard 0.5.2, plotly 4.10.0, ggplot2 2.3.3.5
edit Thanks to the answer below, I realize I made a typo in the conditional statement (ouput
in lieu of output
), which was also very clear from the error messages.
I think I found a solution, now I do not use the select input to show/hide the conditional panels.
---
title: "fdb_reprex"
author: "FMKerchof"
runtime: shiny
output:
flexdashboard::flex_dashboard:
orientation: rows
inlcudes:
navbar:
- { title: "More info", href: "https://github.com/FMKerckhof", align: right }
fontsize: 9pt
editor_options:
chunk_output_type: console
---
```{r setup, include=FALSE}
# Set knitr options ----
knitr::opts_chunk$set(echo = TRUE)
# load packages ----
library(shiny)
library(shinydashboard)
library(ggplot2)
library(plotly)
library(shinyjs)
# toy dataset ----
inputlist <- list(
fulliris=iris,
irisnoseplen=iris[,-1],
irisnopetlen=iris[,c(1,2,4,5)]
)
```
Inputs {.sidebar}
=======================================================================
```{r datasetsel, echo = FALSE}
renderUI(
inputPanel(
selectInput(
"datasetsel", label = "Choose your dataset:",
choices = unique(names(inputlist)),
selected = unique(names(inputlist))[2]),
)
)
selected_data <- reactive({
inputlist[[input$datasetsel]]
}) |>
bindEvent(input$datasetsel)
```
Sepals {data-icon="fa-leaf"}
=====================================
Row {.tabset}
-------------------------------------
### Sepal widths
```{r sepwidthplotly, echo=FALSE}
output$p1 <- renderPlotly({
req(selected_data())
p1 <- selected_data() |>
ggplot(aes(y=Sepal.Width,fill=Species,x=Species)) +
geom_boxplot() +
theme_bw()
ggplotly(p1)
})
plotlyOutput("p1", width = "auto", height = "auto")
```
### Sepal lengths
```{r seplenplotly, echo=FALSE}
output$p2 <- renderPlotly({
p2 <- selected_data() |>
ggplot(aes(y = Sepal.Length, fill = Species, x = Species)) +
geom_boxplot() +
theme_bw()
ggplotly(p2)
})
output$evalseplen = reactive({
is.null(selected_data()$Sepal.Length)
})
output$noseplentext <- renderText({
"No Sepal Lengths in the selected dataset"
})
outputOptions(output, "evalseplen", suspendWhenHidden = FALSE)
conditionalPanel(
condition = "output.evalseplen",
textOutput("noseplentext")
)
conditionalPanel(
condition = "!output.evalseplen",
plotlyOutput("p2",width="auto",height="auto")
)
```