Change what I render based on checkbox input in shiny - r

I'm trying to create a web app where a user can input some data and have it analyzed. If the user doesn't want to upload data and would rather see an example, I want to display an image rather than a plot. Is there a way to decide when to use renderPlot and renderImage based on user input? My solution so far is:
(in my ui.R inside of a fluid page):
conditionalPanel(
condition = "output.useExample == true",
imageOutput("allPCA.image")
),
conditionalPanel(
condition = "output.useExample == false",
plotOutput("allPCA.plot")
)
And I have two functions in my output:
output$allPCA.image <- renderImage({
list(src = "./static/pca.all.png",
contentType = 'image/png',
alt = "Example PCA")
}, deleteFile=FALSE)
output$allPCA.plot <- renderPlot({
plot(stuff))}
Is there a way to do this?

Following an answer for this example renderImage NOT DISPLAYING - R Shiny (only alt text) You can do the following:
rm(list = ls())
library(shiny)
runApp(list(
ui = fluidPage(
titlePanel("Plot or Example?"),
sidebarLayout(
sidebarPanel(
selectInput("my_choices", "Example or Plot",choices = c("Plot", "Example"), selected = 1),width=2),
mainPanel(
conditionalPanel(
condition = "input.my_choices == 'Plot'",
plotOutput('my_test1')
),
conditionalPanel(
condition = "input.my_choices == 'Example'",
uiOutput("my_test2")
)
)
)
),
server = function(input, output) {
output$my_test1 <- renderPlot({plot(runif(100))})
output$my_test2 <- renderUI({
images <- c("http://www.i2symbol.com/images/abc-123/o/white_smiling_face_u263A_icon_256x256.png")
tags$img(src= images)
})
}
))

Related

how to use data output from reactive function as condition in conditional pannel

I am trying to read data and if the data has observation , the further UI has to expand. But the conditional Pannel is not working .
Here is the part of the UI and server code.
UI Code:
tabPanel("DMC 1.1", fluid = TRUE, useShinyjs(),
column(width=12,wellPanel(div(style = 'height:120px;',
fluidRow(column(width=9,style = "font-size: 12px;",fileInput("analysis_data2", label = "Import data", accept = c(".csv",".sas7bdat",".xls",".xpt"))))
)),
conditionalPanel(condition = "output.dataUpload", wellPanel(fluidRow(
column(width=5,textInput("subset","Subsettign Condition",value="")),
column(width=5,textInput("byvar","By Variable",value="")),
column(width=5,textInput("subgrp","SubGroup Variable",value="")),
column(width=5,textInput("trtvar","Treatment Variable",value="")),
column(width=5,textInput("xaxisvar","X Axis Variable",value="")),
column(width=5,textInput("yaxisvar","Y Axis Variable",value=""))
)))
)
)
Server Code:
#################Tab 2 - DMC 2.0#########################
analysis_d <- reactive({data_read(datain=input$analysis_data2)})
output$dataUpload <- reactive({return(!is.null(isolate(analysis_d())))})
outputOptions(output, 'dataUpload', suspendWhenHidden=FALSE)
This app will make an additional text input files available in the UI if the uploaded csv file contains at least one row:
library(shiny)
ui <- fluidPage(
fileInput("file", "File"),
conditionalPanel(
condition = "output.available",
textInput("additional_input", "additional input")
)
)
server <- function(input, output, session) {
data <- reactive(read.csv(input$file$datapath))
output$available <- reactive(nrow(data()) >= 1)
outputOptions(output, "available", suspendWhenHidden = FALSE)
}
shinyApp(ui, server)

Using Conditional Panel in Shiny to Render Plots at the Same Time

This is a reproducible example. I'm trying to understand using the conditionalpanel function under shiny.
How do I tweak the code in a manner such that when I check both checkboxes, the plot and image will be rendered together? (with the plot on the top and image at the bottom on main panel)
library(shiny)
ui = fluidPage(
titlePanel("Plot or Example?"),
sidebarLayout(
sidebarPanel(
checkboxGroupInput("my_choices", "Example or Plot",choices = c("Plot", "Example"), selected = 1),width=2),
mainPanel(
conditionalPanel(
condition = "input.my_choices == 'Plot'",
plotOutput('my_test1')
),
conditionalPanel(
condition = "input.my_choices == 'Example'",
uiOutput("my_test2")
)
)
)
)
server = function(input, output) {
output$my_test1 <- renderPlot({plot(runif(100))})
output$my_test2 <- renderUI({
images <- c("http://www.i2symbol.com/images/abc-123/o/white_smiling_face_u263A_icon_256x256.png")
tags$img(src= images)
})
}
There are several things to do.
First, your selected argument of checkboxGroupInput should match one of the choices. Here I changed it to "Plot".
Second, I used "input.my_choices.includes('Example') && input.my_choices.includes('Plot')" as the condition when both are selected.
Third, Shiny doesn't allow the same output to be used more than once. To get around that, I made duplicates of the outputs in the server code, and referenced the duplicated names in the conditional Panel for the condition both boxes are checked.
library(shiny)
ui = fluidPage(
titlePanel("Plot or Example?"),
sidebarLayout(
sidebarPanel(
checkboxGroupInput("my_choices", "Example or Plot",choices = c("Plot", "Example"), selected = "Plot"),width=2),
mainPanel(
conditionalPanel(
condition = "input.my_choices == 'Plot'",
plotOutput("my_test1")
),
conditionalPanel(
condition = "input.my_choices == 'Example'",
uiOutput("my_test2")
),
conditionalPanel(
condition = "input.my_choices.includes('Example') && input.my_choices.includes('Plot')",
plotOutput("my_test1a"),
uiOutput("my_test2a")
)
)
)
)
server = function(input, output) {
output$my_test1 <- output$my_test1a <- renderPlot({plot(runif(100))})
output$my_test2 <- output$my_test2a <- renderUI({
images <- c("http://www.i2symbol.com/images/abc-123/o/white_smiling_face_u263A_icon_256x256.png")
tags$img(src= images)
})
}
shinyApp(ui, server)

R Shiny reactive triggered by navigating to particular tabPanel in navbarPage

writing with a shiny question. I have a navbarPage, id = "navbar", and in the navbarMenu user can select one among several tabPanels. Each tabPanel is assigned a value (value = 1, value = 2, etc). So input$navbar is reactive value with the value of the selected tabPanel.
I have a reactive expression defined which reacts to the changing of the tabPanel (reacts based on input$navbar). What I actually want is for this to react to navigating to a particular tabPanel, but not navigating away from that tabPanel. So, when input$navbar changes from 1 to 2 I want a reaction, but when changing from 2 to 1 no reaction. How can I achieve this?
Here is relevant snippet of my code, I don't think I need a full reproducible example for this but let me know if I'm wrong.
#ui snippet
navbarPage(id = "navbar",
navbarMenu(title = "Title",
tabPanel(title = "tp1", value = 1),
tabPanel(title = "tp2", value = 2),
#more tabPanels and ui stuff...
#server snippet
rctvfx <- reactive({
#want this to react only when input$navbar changes from ==1 to ==2
input$navbar
isolate({
#do stuff
})
})
You can use an if statement. This makes sure the code only runs if the user navigated to the corresponding tab.
library(shiny)
shinyApp(
ui = navbarPage(
"App Title",
id = "navbar",
tabPanel("Plot"),
navbarMenu(
"More",
tabPanel("Summary"),
"----",
"Section header",
tabPanel("Table")
)
),
server = function(input, output){
observe({
if (req(input$navbar) == "Table")
message("Table has been selected")
if (req(input$navbar) == "Plot")
message("Plot has been selected")
})
}
)
I would recomment do use observe rather than reactive to make sure everything runs even if all observers for the reactive are idle.
Another example of the same answer as above
library(shiny)
shinyApp(
ui = navbarPage(
"App Title",
id = "navbar",
tabPanel("Plot"),
navbarMenu(
"More",
tabPanel("Summary"),
tabPanel("Table"),
mainPanel(dataTableOutput("d"))
)
),
server = function(input, output){
output$d = renderDataTable({
if ((input$navbar) == "Table") {
head(mtcars)
} else {
((input$navbar) == "Plot")
head(iris)
}
})
}
)

Using input in the UI component of Shiny R

I'd like to know if there is a way to use an input in the UI component.
This is my sample code:
shinyApp(
ui <- fluidPage(
column(12,fluidRow(column(4, inputPanel(
selectInput("dx", label = "Diagnosis:",
choices = DX, selected = "LOW BACK PAIN")
))
)),
lapply(unique(allProc[dx.x==input$dx])$pat), function(patient) {
fluidRow(column(1, tags$p(patient)),
column(11, lapply(unique(allProc[pat == patient & dx.x == input$dx])$Clinic),
function(clinic){
fluidRow(column(1, tags$p(clinic)),
column(10, plotOutput(outputId = paste(patient, clinic), height = "100%")))
})))
})
),
server <- function(input, output) {
plot
)
Obviously this is wrong.. I can't just do allProc[dx.x==input$dx]), but the idea is the same. How would I filter in the UI component an element user selects in the same component?
TIA!

Shiny conditional panel

In my app I want the user to choose a folder, and the to choose a file from that folder.
I thought to use conditionalPanel() so the user will see only the first button until he pick's the folder. I wrote this code but I get this error message, 'object 'input' is not found', what would be the right way to do this? And is it a problem to put a conditional panel in an absolute panel?
library(shiny)
library(ggplot2)
ui <- shinyUI(fluidPage(
titlePanel(""),
fluidRow(
# select input for selecting a folder
column(2, absolutePanel(fixed = TRUE, width = '180px',
selectInput("pick_folder", label = '', selected='choose_a_folder',
choices = setNames(as.list(c('choose_a_folder', basename(setdiff(list.dirs(recursive = FALSE),'.')))),
c('choose_a_folder', basename(setdiff(list.dirs(recursive = FALSE),'.'))))))),
# select input for selecting a file absolutePanel then conditionalPanel
column(2, absolutePanel(fixed = TRUE, width = '180px',
conditionalPanel(condition="input.pick_folder==choose_a_folder",
selectInput('pick_file', label = '', selected = 'choose_a_file',
choices = setNames(as.list(c('choose_a_file', basename(setdiff(list.files(path=input$pick_folder ,recursive = FALSE),'.')))),
c('choose a file', basename(setdiff(list.files(path=input$pick_folder ,recursive = FALSE),'.')))))))),
),
fluidRow(
#plot
plotOutput('my_plot')
)))
# server
server <- shinyServer(function(input, output) {
output$my_plot <- renderPlot({
dat <- read.table(file=paste(input$pick_folder, input$pick_file, sep='/'))
# some plots over dat
})
})
shinyApp(ui, server)
The probem arises from trying to dynamically create the choices for the file selection inside the ui part of your app. The way you should do this is to create the dynamic part of the ui (Your file selection) in your server part using uiOutput and renderUI
The following code seems to do what you describe you want:
library(shiny)
library(ggplot2)
ui <- shinyUI(fluidPage(
titlePanel(""),
fluidRow(
# select input for selecting a folder
column(2, absolutePanel(fixed = TRUE, width = '180px',
selectInput("pick_folder", label = '', selected='choose_a_folder',
choices = setNames(as.list(c('choose_a_folder', basename(setdiff(list.dirs(recursive = FALSE),'.')))),
c('choose_a_folder', basename(setdiff(list.dirs(recursive = FALSE),'.'))))))),
# select input for selecting a file absolutePanel then conditionalPanel
column(2, absolutePanel(fixed = TRUE, width = '180px',
conditionalPanel(condition="input.pick_folder==choose_a_folder",
# Insert a dynamic bit of UI
uiOutput("fileselection")
)
)
)
),
fluidRow(
#plot
plotOutput('my_plot')
)))
# server
server <- shinyServer(function(input, output) {
output$my_plot <- renderPlot({
dat <- read.table(file=paste(input$pick_folder, input$pick_file, sep='/'))
# some plots over dat
})
output$fileselection <- renderUI({ #Define the dynamic UI
selectInput('pick_file', label = '', selected = 'choose_a_file',
choices = setNames(as.list(c('choose_a_file', basename(setdiff(list.files(path=input$pick_folder ,recursive = FALSE),'.')))),
c('choose a file', basename(setdiff(list.files(path=input$pick_folder ,recursive = FALSE),'.'))
)
)
)
})
})
shinyApp(ui, server)

Resources