Save reactive value of selectInput when switching tabs - r

I have a selectInput menu that comes up when I have a certain tab open in my window. I use the same selectInput (inside renderMenu) for multiple tabs. I would like to figure out how to save the value chosen on one tab so it will be the chosen value when switching tabs. Here, for example, if I choose the mtcars plots tab and select 'blue', and then switch to mtcars plots 2, I would like the selected color to be kept at 'blue' rather than switching back to the first option of red.
Yes, I am aware that I am not currently doing anything with the colors, I will add that usage in later.
library(shiny)
library(shinythemes)
library(shinydashboard)
library(tidyverse)
options(warn=-1)
data(iris)
data(mtcars)
# Define UI for application that draws a histogram
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(id = "menume",
sidebarMenuOutput("colormenu"),
menuItem("MTCARS", tabName = "mt", icon = icon("user-tie")),
selectInput("mtvar", "Choose a variable", choices = colnames(mtcars)),
menuItem("IRIS", icon = icon("envelope-open-text"), tabName = "ir"),
selectInput("irvar", "Choose a variable", choices = colnames(iris))
)
),
dashboardBody(
tabItems(
tabItem("mt", uiOutput("mttabs")),
tabItem("ir", uiOutput("irtabs"))
)
)
)
# ui <- secure_app(ui, enable_admin = TRUE)
# Begin Server ----------------------------------------------
server <- function(input, output, session) {
output$colormenu = renderMenu({
req((input$menume=="mt"& input$mtcarstabsall%in%c(2,3))||
(input$menume=="ir"& input$iristabsall%in%c(5,6)))
selectInput("colorme", "Choose a color", c("red", "yellow", "green", "blue", "black"))
})
output$mttabs = renderUI({
output$mtcarsplot1=renderPlot({
ggplot(mtcars, aes_string(x = input$mtvar)) + stat_bin(nbins = 10)
})
output$mtcarsplot2=renderPlot({
ggplot(mtcars, aes_string(x = input$mtvar)) + geom_density()
})
output$mtcarstable1=renderTable({
tabme= head(mtcars, 5)
tabme
})
tabsetPanel(id = "mtcarstabsall",
tabPanel(id = "mttable","MTcars tables",value=1,
fluidRow(box(title = "Table 1", tableOutput("mtcarstable1")))
),
tabPanel(id = "mtplots","mtcars plots",value=2,
fluidRow(box(title = "Plot1", plotOutput("mtcarsplot1"))
)),
tabPanel(id = "mtplots2","mtcars plots 2",value=3,
fluidRow(box(title = "Plot1", plotOutput("mtcarsplot2")))))
})
output$irtabs = renderUI({
output$irisplot1=renderPlot({
ggplot(iris, aes_string(x = input$irvar)) + stat_bin(nbins = 10)
})
output$irisplot2=renderPlot({
ggplot(iris, aes_string(x = input$irvar)) + geom_density()
})
output$iristable1=renderTable({
tabme = head(iris, 5)
tabme
})
tabsetPanel(id = "iristabsall",
tabPanel(id = "mttable","iris tables",value=4,
fluidRow(box(title = "Table 1", tableOutput("iristable1")))
),
tabPanel(id = "irisplots","iris plots",value=5,
fluidRow(box(title = "Plot1", plotOutput("irisplot1"))
)),
tabPanel(id = "irisplots2","iris plots 2",value=6,
fluidRow(box(title = "Plot2", plotOutput("irisplot2"))
)))
})
}
shinyApp(ui, server)

The issue is that the color menu is re-rendering every time you switch tabs and so it resets the selected value. For something like this what you want to do instead is just show/hide the element rather than add/remove it (which is what you're currently doing with req()).
You could use a conditionalPanel in your menu or use the shinyjs package with something like the below (remembering to add shinyjs::useShinyjs() to your ui, to show/hide the color menu:
output$colormenu = renderMenu({
# Remove the req
selectInput("colorme", "Choose a color", c("red", "yellow", "green", "blue", "black"))
})
observe({
# Show/hide menu based on condition using shinyjs::toggle
show_menu_condition <- (input$menume=="mt"& input$mtcarstabsall%in%c(2,3)) || (input$menume=="ir"& input$iristabsall%in%c(5,6))
shinyjs::toggle("colormenu",
condition = show_menu_condition)
})

Related

Reactive values not working on nested tabsetPanel

I am trying to create a shinyApp with a a set of tabsetPanels within tabsetPanels. However, if on one of those embedded tabsetPanels I have a tabPanel that has a reactive value (a radioButton or a checkboxInput, for example), the reactive item doesn't work, and its value in input is NULL. This is causing some of my graphs to not render properly, if they are in a box with a selector. Any idea of why this is happening or what I can do to fix it would be great.
A reprex app (in this case, the checkBoxInput for the y axis is working, but on my actual app it is not.)
library(shiny)
library(shinythemes)
library(shinydashboard)
library(shinyjs)
library(tidyverse)
options(warn=-1)
data(iris)
data(mtcars)
# Define UI for application that draws a histogram
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
shinyjs::useShinyjs(),
sidebarMenu(id = "menume",
#selectInput("which unit", "Choose a unit", choices = c("aa", "bb", "cc", "dd")),
selectInput("colorme", "Choose a color", c("red", "yellow", "green", "blue", "black")),
#sidebarMenuOutput("colormenu"),
menuItem("MTCARS", tabName = "mt", icon = icon("user-tie")),
selectInput("mtvar", "Choose a variable", choices = colnames(mtcars)),
menuItem("IRIS", icon = icon("envelope-open-text"), tabName = "ir"),
selectInput("irvar", "Choose a variable", choices = colnames(iris))
)
),
dashboardBody(
tabItems(
tabItem("mt", uiOutput("mttabs")),
tabItem("ir", uiOutput("irtabs"))
)
)
)
# ui <- secure_app(ui, enable_admin = TRUE)
# Begin Server ----------------------------------------------
server <- function(input, output, session) {
# output$colormenu = renderMenu({
# # Remove the req
# selectInput("colorme", "Choose a color", c("red", "yellow", "green", "blue", "black"))
#
#
# })
permission_color = reactive({
if(input$colorme =="green"){
TRUE
}else{
FALSE
}
})
output$mttabs = renderUI({
output$mtcarsplot1=renderPlot({
myplot = ggplot(mtcars, aes_string(x = input$mtvar)) + stat_bin(nbins = 10)
if(input$tenfoldmt == TRUE){myplot = myplot+ylim(c(0,10))}
myplot
})
output$mtcarsplot2=renderPlot({
ggplot(mtcars, aes_string(x = input$mtvar)) + geom_density()
})
output$mtcarstable1=renderTable({
tabme= head(mtcars, 5)
tabme
})
if(permission_color()==TRUE){
tabsetPanel(id = "mtcarstabsall",
tabPanel("Plots",
tabsetPanel(id = "mtplotsall",
tabPanel(id = "mtplots","mtcars plots",value=2,
fluidRow(box(title = "Plot1",
checkboxInput("tenfoldmt", "Y axis lim 10?", value = FALSE),
plotOutput("mtcarsplot1"))
)),
tabPanel(id = "mtplots2","mtcars plots 2",value=3,
fluidRow(box(title = "Plot2", plotOutput("mtcarsplot2")))))
),
tabPanel("Tables",
tabsetPanel(id = "mttables",
tabPanel(id = "mttable","MTcars tables",value=1,
fluidRow(box(title = "Table 1", tableOutput("mtcarstable1")))
)))
)
} else{
tabsetPanel(id = "mtcarstabsall",
tabPanel("Plots",
tabsetPanel(id = "mtplotsall",
tabPanel(id = "mtplots","mtcars plots",value=2,
fluidRow(box(title = "Plot1",
checkboxInput("tenfoldmt", "Y axis lim 10?", value = FALSE),
plotOutput("mtcarsplot1"))
)),
tabPanel(id = "mtplots2","mtcars plots 2",value=3,
fluidRow(box(title = "Plot2", plotOutput("mtcarsplot2")))))
)
)
}
})
output$irtabs = renderUI({
output$irisplot1=renderPlot({
myplot = ggplot(iris, aes_string(x = input$irvar)) + stat_bin(nbins = 10)
if(input$tenfoldir == TRUE){myplot = myplot+ylim(c(0,10))}
myplot
})
output$irisplot2=renderPlot({
ggplot(iris, aes_string(x = input$irvar)) + geom_density()
})
output$iristable1=renderTable({
tabme = head(iris, 5)
tabme
})
if(permission_color()==TRUE){
tabsetPanel(id = "iristabsall",
tabPanel("Plots",
tabsetPanel(id = "irisplotsall",
tabPanel(id = "irisplots","iris plots",value=5,
fluidRow(box(title = "Plot1",
checkboxInput("tenfoldir", "Y axis lim 10?", value = FALSE),
plotOutput("irisplot1"))
)),
tabPanel(id = "irisplots2","iris plots 2",value=6,
fluidRow(box(title = "Plot2", plotOutput("irisplot2"))
)))
),
tabPanel("Tables",
tabsetPanel(id = "iristables",
tabPanel(id = "irtable","iris tables",value=4,
fluidRow(box(title = "Table 1", tableOutput("iristable1")))
)))
)
} else{
tabsetPanel(id = "iristabsall",
tabPanel("Plots",
tabsetPanel(id = "irisplotsall",
tabPanel(id = "irisplots","iris plots",value=5,
fluidRow(box(title = "Plot1",
checkboxInput("tenfoldir", "Y axis lim 10?", value = FALSE),
plotOutput("irisplot1"))
)),
tabPanel(id = "irisplots2","iris plots 2",value=6,
fluidRow(box(title = "Plot2", plotOutput("irisplot2"))
)))
))
}
})
}
shinyApp(ui, server)

Shinydashboard - show or hide tab based on log in info AND selectinput

I'm working on a shinydashboard that is secured using shinymanager and I am having trouble. I want to make a tab appear or disappear based on two bits of information. I have saved in my shinymanager credentials a user code that says what their home organization is. In my app I also have a selectInput that allows the user to choose a particular user code. I have tabs that I would like to show only if the user code for that user's credentials match the selected user code from selectInput. So for example, in the below example, if I had in res_auth a field called 'unit' with the choices aa, bb, cc, dd, ee - and the user who logs in is in unit aa, and they choose aa from the selectInput, then the iris tabs would show up - but if they choose bb they would not see the iris tabs.
library(shiny)
library(shinythemes)
library(shinymanager)
library(shinydashboard)
library(tidyverse)
options(warn=-1)
data(iris)
data(mtcars)
tabset1 = tabsetPanel(id = "mtcars",
tabPanel(id = "mtplots","mtcars plots",
fluidRow(box(title = "Plot1", plotOutput("mtcarsplot1"))
)),
tabPanel(id = "mttable","MTcars tables",
fluidRow(box(title = "Table 1", tableOutput("mtcarstable1")))
))
tabset2 = tabsetPanel(id = "iris",
tabPanel(id = "iris","iris plots",
fluidRow(box(title = "Plot1", plotOutput("irisplot1"))
)),
tabPanel(id = "mttable","iris tables",
fluidRow(box(title = "Table 1", tableOutput("iristable1")))
))
# Define UI for application that draws a histogram
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
selectInput("which unit", "Choose a unit", choices = c("aa", "bb", "cc", "dd")),
menuItem("MTCARS", tabName = "mt", icon = icon("user-tie")),
selectInput("mtvar", "Choose a variable", choices = colnames(mtcars)),
# RIGHT HERE
menuItem("IRIS", icon = icon("envelope-open-text"), tabName = "ir"),
selectInput("irvar", "Choose a variable", choices = colnames(iris))
)
),
dashboardBody(
tabItems(
tabItem("ir", tabset2),
tabItem("mt", tabset1)
)
)
)
ui <- secure_app(ui, enable_admin = TRUE)
# Begin Server ----------------------------------------------
server <- function(input, output, session) {
res_auth <- secure_server(
check_credentials = check_credentials("mycredentials.sqlite")
)
output$mtcarsplot1=renderPlot({
ggplot(mtcars, aes_string(x = input$mtvar)) + stat_bin(nbins = input$irislines)
})
output$irisplot1=renderPlot({
ggplot(iris, aes_string(x = input$irvar)) + stat_bin(nbins = input$mtlines)
})
output$mtcarstable1=renderTable({
head(mtcars, input$mtlines)
})
output$iristable1=renderTable({
head(iris, input$irislines)
})
}
shinyApp(ui, server)
First replace the line below # RIGHT HERE with:
uiOutput("test"),
Then add a function like this to the server:
output$test <- renderUI({
if(input$`which unit`=="aa") {
menuItem("IRIS", icon = icon("envelope-open-text"), tabName = "ir")
}
})
You will need to add a condition to the if to require their credentials to match in your situation, but this is essentially what you want.

How to change the theme in semantic.dashboard?

I followed the tutorial on creating a dashboard with Shiny and semantic.dashboard: https://appsilon.com/create-outstanding-dashboards-with-the-new-semantic-dashboard-package/
The example uses a custom theme named "cerulean", but it doesn't appear when running the app. Changing the theme to another one doesn't have any impact either. Does someone know the correct way to change the theme? The example code uses the theme option of dashboardPage as described in the documentation. I didn*t change anything, but the screenshots from the tutorial look different.
Thanks a lot for your help!
library(shiny)
library(semantic.dashboard)
library(ggplot2)
library(plotly)
library(DT)
ui <- dashboardPage(
dashboardHeader(color = "blue",title = "Dashboard Demo", inverted = TRUE),
dashboardSidebar(
size = "thin", color = "teal",
sidebarMenu(
menuItem(tabName = "main", "Main", icon = icon("car")),
menuItem(tabName = "extra", "Extra", icon = icon("table"))
)
),
dashboardBody(
tabItems(
selected = 1,
tabItem(
tabName = "main",
fluidRow(
box(width = 8,
title = "Graph 1",
color = "green", ribbon = TRUE, title_side = "top right",
column(width = 8,
plotOutput("boxplot1")
)
),
box(width = 8,
title = "Graph 2",
color = "red", ribbon = TRUE, title_side = "top right",
column(width = 8,
plotlyOutput("dotplot1")
)
)
)
),
tabItem(
tabName = "extra",
fluidRow(
dataTableOutput("carstable")
)
)
)
), theme = "cerulean"
)
server <- shinyServer(function(input, output, session) {
data("mtcars")
colscale <- c(semantic_palette[["red"]], semantic_palette[["green"]], semantic_palette[["blue"]])
mtcars$am <- factor(mtcars$am,levels=c(0,1),
labels=c("Automatic","Manual"))
output$boxplot1 <- renderPlot({
ggplot(mtcars, aes(x = am, y = mpg)) +
geom_boxplot(fill = semantic_palette[["green"]]) +
xlab("gearbox") + ylab("Miles per gallon")
})
output$dotplot1 <- renderPlotly({
ggplotly(ggplot(mtcars, aes(wt, mpg))
+ geom_point(aes(colour=factor(cyl), size = qsec))
+ scale_colour_manual(values = colscale)
)
})
output$carstable <- renderDataTable(mtcars)
})
shinyApp(ui, server)

How to make conditionalPanel show menu item based on active tab in shinydashboard

I am trying to make a shinydashboard with a bunch of different tabs that show up for different types of data. What I want is when a certain tabItem is selected, for a selectInput item to show up in the sidebar. (Eventually I would like for this to happen for multiple tabs, but I will work on just one tab for now.)
Here's an executable example of what I want:
library(shiny)
library(shinythemes)
library(shinydashboard)
library(tidyverse)
options(warn=-1)
data(iris)
data(mtcars)
tabset1 = tabsetPanel(id = "mtcars",
tabPanel(id = "mtplots","mtcars plots",
fluidRow(box(title = "Plot1", plotOutput("mtcarsplot1"))
)),
tabPanel(id = "mttable","MTcars tables",
fluidRow(box(title = "Table 1", tableOutput("mtcarstable1")))
))
tabset2 = tabsetPanel(id = "iris",
tabPanel(id = "iris","iris plots",
fluidRow(box(title = "Plot1", plotOutput("irisplot1"))
)),
tabPanel(id = "mttable","iris tables",
fluidRow(box(title = "Table 1", tableOutput("iristable1")))
))
# Define UI for application that draws a histogram
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("MTCARS", tabName = "mt", icon = icon("user-tie")),
selectInput("mtvar", "Choose a variable", choices = colnames(mtcars)),
sliderInput("mtlines", "Number of lines", 1,50,10),
# **I would like a conditionalPanel here such that if the tab mtplots is selected, a selectInput as below shows up - but only is visible for that tab **
#selectInput("colorvar", "choose a color", choices = c("red", "yellow", "green", "blue"))
menuItem("IRIS", icon = icon("envelope-open-text"), tabName = "ir"),
selectInput("irvar", "Choose a variable", choices = colnames(iris)),
sliderInput("irislines", "Number of lines", 1,50,10)
)
),
dashboardBody(
tabItems(
tabItem("ir", tabset2),
tabItem("mt", tabset1)
)
)
)
# Begin Server ----------------------------------------------
server <- function(input, output, session) {
output$mtcarsplot1=renderPlot({
ggplot(mtcars, aes_string(x = input$mtvar)) + geom_histogram()
})
output$irisplot1=renderPlot({
ggplot(iris, aes_string(x = input$irvar)) + geom_histogram()
})
output$mtcarstable1=renderTable({
head(mtcars, input$mtlines)
})
output$iristable1=renderTable({
head(iris, input$irislines)
})
}
shinyApp(ui, server)
You can use input$mtcars to determine which tab in the tabsetPanel is active. To render a dynamic/conditional UI element, you can use uiOutput/renderUI. In renderUI, I use req to only render it if the correct tabPanel is chosen:
library(shiny)
library(shinythemes)
library(shinydashboard)
library(tidyverse)
data(iris)
data(mtcars)
tabset1 = tabsetPanel(id = "mtcars",
tabPanel(id = "mtplots","mtcars plots",
fluidRow(box(title = "Plot1", plotOutput("mtcarsplot1"))
)),
tabPanel(id = "mttable","MTcars tables",
fluidRow(box(title = "Table 1", tableOutput("mtcarstable1")))
))
tabset2 = tabsetPanel(id = "iris",
tabPanel(id = "iris","iris plots",
fluidRow(box(title = "Plot1", plotOutput("irisplot1"))
)),
tabPanel(id = "mttable","iris tables",
fluidRow(box(title = "Table 1", tableOutput("iristable1")))
))
# Define UI for application that draws a histogram
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("MTCARS", tabName = "mt", icon = icon("user-tie")),
selectInput("mtvar", "Choose a variable", choices = colnames(mtcars)),
sliderInput("mtlines", "Number of lines", 1,50,10),
# **I would like a conditionalPanel here such that if the tab mtplots is selected, a selectInput as below shows up - but only is visible for that tab **
uiOutput("UI_conditional_input"),
menuItem("IRIS", icon = icon("envelope-open-text"), tabName = "ir"),
selectInput("irvar", "Choose a variable", choices = colnames(iris)),
sliderInput("irislines", "Number of lines", 1,50,10)
)
),
dashboardBody(
tabItems(
tabItem("ir", tabset2),
tabItem("mt", tabset1)
)
)
)
# Begin Server ----------------------------------------------
server <- function(input, output, session) {
output$mtcarsplot1=renderPlot({
ggplot(mtcars, aes_string(x = input$mtvar)) + geom_histogram()
})
output$irisplot1=renderPlot({
ggplot(iris, aes_string(x = input$irvar)) + geom_histogram()
})
output$mtcarstable1=renderTable({
head(mtcars, input$mtlines)
})
output$iristable1=renderTable({
head(iris, input$irislines)
})
output$UI_conditional_input <- renderUI({
req(input$mtcars == "mtcars plots")
selectInput("colorvar", "choose a color", choices = c("red", "yellow", "green", "blue"))
})
}
shinyApp(ui, server)

multiple plot outputs R in different tabs (shinyDashboard)

The code currently produces the dashboard and the side panels for the plots, it also produces one plot. (which ever is called first in the final line). If anyone has any suggestions on how to produce two separate plots on two different tabs using a shiny dashboard it would be much appreciated. Tearing my hair out!
https://lot1bct.shinyapps.io/lot1bct/
My current state, minus the "fuels" tab and second plot for reference on what i'm aiming for.
The code below has the second plot code mocked up along with the additional dashboard code in the "fuels" tab which the live version does not.
## app.R ##
library(shinydashboard)
library(shiny)
library(ggplot2)
dataset <- testData
fuelData <- fuelDataCSV
tyreData <- tyreDataCSV
ui <- dashboardPage(
skin="green",
dashboardHeader(title = "Strategy Dashboard v0.1",
dropdownMenu(type = "tasks", badgeStatus = "success",
taskItem(value = 10, color = "green",
"Documentation"
),
taskItem(value = 30, color = "aqua",
"UI"
),
taskItem(value = 15, color = "yellow",
"Data Developmentt"
)
)),
## Sidebar content
dashboardSidebar(
sidebarMenu(
menuItem("Home", tabName = "home", icon = icon("home")),
menuItem("Tyres", tabName = "tyres", icon = icon("circle-o")),
menuItem("Fuels and Lubericants", tabName = "fuel", icon = icon("flask")),
menuItem("Times", tabName = "times", icon = icon("clock-o")),
menuItem("Documentation", tabName = "documentation", icon = icon("sticky-note-o")),
menuItem("Downloads", tabName = "downloads", icon = icon("download")),
# Custom CSS to hide the default logout panel
tags$head(tags$style(HTML('.shiny-server-account { display: none; }'))),
# The dynamically-generated user panel
uiOutput("userpanel")
)
),
## Header Content
## Body content
dashboardBody(
tabItems(
# First tab content
tabItem(tabName = "home",
h2("UI Tests"), p("This published version is the first test build (version 0.1).")
),
# Second tab content
tabItem(tabName = "tyres",
h2("Tyre data sets"), fluidPage(
sidebarPanel(
sliderInput('sampleSize', 'Sample Size (Laps)', min=1, max=nrow(tyreData),
value=min(20, nrow(tyreData)), step=1, round=0),
selectInput('x', 'X', names(tyreData)),
selectInput('y', 'Y', names(tyreData), names(tyreData)[[2]]),
selectInput('color', 'Color', c('None', names(tyreData))),
checkboxInput('density', 'Density'),
checkboxInput('trend', 'Trend')
),
mainPanel(
plotOutput('plotT')
)
)
),
# Third tab content
tabItem(tabName = "fuel",
h2("Fuel and Lubricant data sets"),
fluidPage(
sidebarPanel(
sliderInput('sampleSize', 'Sample Size (Laps)', min=1, max=nrow(fuelData),
value=min(20, nrow(fuelData)), step=1, round=0),
selectInput('x', 'X', names(fuelData)),
selectInput('y', 'Y', names(fuelData), names(fuelData)[[2]]),
selectInput('color', 'Color', c('None', names(fuelData))),
checkboxInput('density', 'Density'),
checkboxInput('trend', 'Trend')
),
mainPanel(
plotOutput('plotF')
)
)
),
# Fourth tab content
tabItem(tabName = "times",
h2("Times data sets")
),
# Fifth tab content
tabItem(tabName = "documentation",
h2("Documentation")
),
# Sixth tab content
tabItem(tabName = "downloads",
h2("Downloads")
)
)
)
)
tyrePlot <- function(input, output) {
tyreData <- reactive({
tyreDataCSV[sample(nrow(tyreDataCSV), input$sampleSize),]
})
output$plotF <- renderPlot({
p <- ggplot(tyreData(), aes_string(x=input$x, y=input$y)) + geom_point()
if (input$color != 'None')
p <- p + aes_string(color=input$color)
if (input$density)
p <- p + geom_density_2d()
if (input$trend)
p <- p + geom_smooth()
print(p)
}, height=700)
}
fuelPlot <- function(input, output) {
fuelData <- reactive({
fuelDataCSV[sample(nrow(fuelDataCSV), input$sampleSize),]
})
output$plotF <- renderPlot({
p <- ggplot(fuelData(), aes_string(x=input$x, y=input$y)) + geom_point()
if (input$color != 'None')
p <- p + aes_string(color=input$color)
if (input$density)
p <- p + geom_density_2d()
if (input$trend)
p <- p + geom_smooth()
print(p)
}, height=700)
}
shinyApp(ui, tyrePlot, fuelPlot)

Resources