UI doesn't update Shiny Dashboard - r

The UI doesn't update the page when I have an input in the sidebar menu. In the example below when I click on "load data" it still shows a menu on the page.
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("About", tabName = "a", icon = icon("info-circle")),
menuItem("Load Data", icon = icon("gear"), tabName = "b",
selectInput(inputId="convertToLog", label="Are X values on log2 scale?",choices=list('Yes'=1,'No'=0),selected=1))
)),
dashboardBody(
tabItems(
tabItem(tabName ="a", "a menu"),
tabItem(tabName ="b", "b menu")
)
)
)
server <- function(input, output) {}
shinyApp(ui, server)

As far as I know, you can/should not put another item in a menuItem, except for subMenuItems. You could use a conditionalPanel to achieve what you want though:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(id="mysidebar",
menuItem("About", tabName = "a", icon = icon("info-circle")),
menuItem("Load Data", icon = icon("gear"), tabName = "b"),
conditionalPanel("input.mysidebar == 'b'",
selectInput(inputId="convertToLog", label="Are X values on log2 scale?",choices=list('Yes'=1,'No'=0),selected=1)),
menuItem('Another tab',tabName='c',icon = icon("gear"))
)
),
dashboardBody(
tabItems(
tabItem(tabName ="a", "a menu"),
tabItem(tabName ="b", "b menu"),
tabItem(tabName ="c", "c menu")
)
)
)
server <- function(input, output) {}
shinyApp(ui, server)
Note that I gave the sidebarMenu an ID to use in the condition of the conditionalPanel, and I added a tab to show that the conditionalPanel does not have to be at the bottom of the menu.
I hope this helps!

Related

Is there a way to adapt datatable width with sidebar width in shinydashboard?

I have the shiny dashboard below and as you see I want to display a datatable inside sidebar but the issue is that the table is much wider. Can I make the table fit in exactly in the sidebar without increasing sidbar width?
library(shiny)
library(shinydashboard)
library(DT)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("Table" , tabname = "my_table", icon = icon("table"),DT::dataTableOutput("example_table")
),
menuItem("Next Widget", tabName = "Other"))),
dashboardBody(
tabItems(
tabItem(tabName = "subMenu", #my_table",
fluidRow(
)),
tabItem(tabName = "Other",
h2("Other tab")
)
)))
server <- function(input, output) {
output$example_table <- DT::renderDataTable(head(mtcars))
}
shinyApp(ui, server)
One quick way is to enable horizontal scrolling for your DT. Then the table will fit the container but be scrollable:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("Table" , tabname = "my_table", icon = icon("table"),DT::dataTableOutput("example_table")
),
menuItem("Next Widget", tabName = "Other"))),
dashboardBody(
tabItems(
tabItem(tabName = "subMenu", #my_table",
fluidRow(
)),
tabItem(tabName = "Other",
h2("Other tab")
)
)))
server <- function(input, output) {
output$example_table <- DT::renderDataTable(head(mtcars), options = list(scrollX=TRUE))
}
shinyApp(ui, server)

Shiny dataTableOutput won't show up if its is under tabItem

My Shiny APP has a simple structure looks like:
ui <- fluidPage(
dashboardPage(
dashboardHeader(title = "My App"),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard",
selectInput('location', 'Please Select a Location', choices= c("A", "B", "C")),
downloadButton(outputId = 'download', lable = "Downlaod"),
menuItem("Widgets", tabName = "widgets", badgeLabel = "new", badgeColor = "green")
)),
# dashboardBody first try (works no problem):
dashboardBody(DT::dataTableOutput(outputId = 'mytable'))
# dashboardBody second try (data table does not appear):
dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
DT::dataTableOutput(outputId = 'mytable')),
tabItem(tabName = "widgets",
h2("Widgets tab content"))
)))
server <- shinyServer(function(input, output, session){
output$mytable<- DT::renderDataTable({```some calculation```})
output$downloadcsv <- downloadHandler(
filename = function(){paste0(sys.Date(),'-mytable.csv')},
content = function(file) {write.csv(```the table from renderDataTable step```, file)}
)}
As you can see, the app includes two different "pages" where the first one is a data table depends on the selectInput.
My app runs perfectly if I don't wrap it with tabItem. However, once I write it under tabItem, the app only shows "Widgets tab content" which is the content of the second tab and does not populate the data table at all (while the download button still works).
I've also tried to add class='active' behind tabName = "dashboard", but it still doesn't work. Plus, I'm not getting any error message.
I'm wondering if anyone knows which step did I go wrong? Any help would be appreciated!
The problem lies in the placement of the table. I have rendered input options outside the menuItem. Check this code below
ui <- fluidPage(
dashboardPage(
dashboardHeader(title = "My App"),
dashboardSidebar(
sidebarMenu(
selectInput('location', 'Please Select a Location', choices= c("A", "B", "C")),
downloadButton(outputId = 'download.csv', lable = "Downlaod"),
menuItem("Dashboard", tabName = "dashboard"),
menuItem("Widgets", tabName = "widgets", badgeLabel = "new", badgeColor = "green")
)),
# dashboardBody first try (works no problem):
#dashboardBody(DT::dataTableOutput(outputId = 'mytable'))
#dashboardBody second try (data table does not appear):
dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
DT::dataTableOutput(outputId = 'mytable')),
tabItem(tabName = "widgets",
h2("Widgets tab content"))
))
))
server <- function(input, output, session){
output$mytable<- DT::renderDataTable({DT::datatable(head(iris))})
output$downloadcsv <- downloadHandler(
filename = function(){paste0(sys.Date(),'-mytable.csv')},
content = function(file) {write.csv(head(iris), file)}
)}
shinyApp(ui=ui, server=server)

shinydashboard: menuSubItem not rendering at start in case of several menuSubItems

I found that menuSubItem content is not rendering in case of several (more than one) tabItems.
Minimal example demonstrating this behavior is below.
The desired behavior is to show content of the tabItem marked as selected = TRUE on startup. Now, the content shows up only after switching between menuSubItems in the sidebar.
How can I make it work?
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "MINIMAL EXAMPLE"),
dashboardSidebar(
sidebarMenuOutput("menu")
),
dashboardBody(
uiOutput("body")
)
)
server <- function(input, output, session) {
output$menu <- renderMenu(
sidebarMenu(
menuItem(text = "TABS", tabName = "TABS", startExpanded = T,
menuSubItem(text = "tab1", tabName="tab1",
icon = icon("cube"), selected = TRUE),
menuSubItem(text = "tab2", tabName="tab2",
icon = icon("cube"), selected = FALSE)
)
)
)
output$body <- renderUI({
tabItems(
tabItem(tabName = "tab1",
h4("MY TEXT 1")
),
tabItem(tabName = "tab2",
h4("MY TEXT 2")
))
})
}
shinyApp(ui = ui, server = server)
Indeed, putting ui elements directly in UI solves it.
But the approach of putting everything inside ui is limited to situations that do not involve using reactive values. As I understand passing reactive value from server to ui is not possible in general (or limited to special cases). Please correct if I am wrong... Thanks
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "MINIMAL EXAMPLE"),
dashboardSidebar(
sidebarMenuOutput("menu")
),
dashboardBody(
tabItems(
tabItem(tabName = "tab1",
h4("MY TEXT 1")
),
tabItem(tabName = "tab2",
h4("MY TEXT 2")
))
)
)
server <- function(input, output, session) {
output$menu <- renderMenu(
sidebarMenu(
menuItem(text = "TABS", tabName = "TABS", startExpanded = T,
menuSubItem(text = "tab1", tabName="tab1",
icon = icon("cube"), selected = TRUE),
menuSubItem(text = "tab2", tabName="tab2",
icon = icon("cube"), selected = FALSE)
)
)
)
}
shinyApp(ui = ui, server = server)
Renaming your output to something other than "body" helps - please see this.
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "MINIMAL EXAMPLE"),
dashboardSidebar(
sidebarMenuOutput("menu")
),
dashboardBody(
uiOutput("myBodyOutput")
)
)
server <- function(input, output, session) {
output$myBodyOutput <- renderUI({
tabItems(
tabItem(tabName = "tab1",
h4("MY TEXT 1")
),
tabItem(tabName = "tab2",
h4("MY TEXT 2")
))
})
output$menu <- renderMenu(
sidebarMenu(id = "sidebarID",
menuItem(text = "TABS", tabName = "TABS", startExpanded = T,
menuSubItem(text = "tab1", tabName="tab1",
icon = icon("cube"), selected = TRUE),
menuSubItem(text = "tab2", tabName="tab2",
icon = icon("cube"), selected = FALSE)
)
)
)
}
shinyApp(ui = ui, server = server)

Periodically switch tab in shinydashboard

In a shinydashboard with several tabs like here
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Sample Shiny"),
dashboardSidebar(
sidebarMenu(
menuItem("Tab 1", tabName = "tab1"),
menuItem("Tab 2", tabName = "tab2")
)
),
dashboardBody(
tabItems(
tabItem(
"tab1",
fluidRow(
box(title = "Foo")
)
),
tabItem(
"tab2",
fluidRow(
box(title = "Bar")
)
)
)
)
)
server <- function(input, output) { }
shinyApp(ui = ui, server = server)
is it possible to let the application switch the active tab periodically? I want to have the dashboard on my screen with switching the active tab every x minutes.
I already checked the Shiny docs for a solution but haven't found an appropriate function. But maybe I simply overlooked such a feature. If Shiny does not offer a suitable feature, is it possible to include some custom JavaScript that does the job?
Here's a way to do it, using invalidateLater and updateTabItems:
app.R:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Sample Shiny"),
dashboardSidebar(
sidebarMenu(
id = 'tabs',
menuItem("Tab 1", tabName = "tab1"),
menuItem("Tab 2", tabName = "tab2")
)
),
dashboardBody(
tabItems(
tabItem(
"tab1",
fluidRow(
box(title = "Foo")
)
),
tabItem(
"tab2",
fluidRow(
box(title = "Bar")
)
)
)
)
)
tabnames = c('tab1', 'tab2')
server <- function(input, output, session) {
#keep track of active tab
active <- reactiveValues(tab = 1)
observe({
#Change every 5 secs, you can set this to whatever you want
invalidateLater(5000,session)
#update tab
isolate(active$tab <- active$tab%%length(tabnames) + 1)
updateTabItems(session,'tabs',tabnames[active$tab])
})
}
shinyApp(ui = ui, server = server)

Shiny ConditionalPanel for Sidebar

I am trying to use update my Shiny Dashboard Sidebar based on the tab selected in the Main body. So when tab "Overall" is selected then this should display the menu items in Conditional Panel 1 (TA.Name1,TA.Name2), and when tab "Other" is selected then the sidebar displays the menu items for conditional panel 2. Data is bellow:
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
conditionalPanel(condition="input.conditionedPanels==1", sidebarMenu(width=150,
menuItem("TA.Name1", tabName = "TA1")),
menuItem("TA.Name2", tabName = "TA2"))),
conditionalPanel(condition="input.conditionedPanels==2",sidebarMenu(width=150,
menuItem("EA.Name1", tabName = "EA1")),
menuItem("EA.Name2", tabName = "EA2"))),
dashboardBody(
tabsetPanel(
tabPanel("Overall",value=1,fluidRow(
column(3,selectInput("PACO", h5("PACO"), levels(OA$PACO)))),
tabItems(
tabItem(tabName = "TA1","TA1"),fluidRow(
box(title="TA.Name1,dygraphOutput("TA1.data")),
box(title="TA.Name2,dygraphOutput("TA2.data")))),
tabItem(tabName = "TA2","TA2")
)),
tabPanel("Other",value=2,fluidRow(
column(3,selectInput("CV", h5("CV"), levels(OA$CV)))),
tabItems(
tabItem(tabName = "EA1","EA1"),fluidRow(
box(title="EA.Name1,dygraphOutput("EA1.data")),
box(title="EA.Name2,dygraphOutput("EA2.data")))),
tabItem(tabName = "EA2","EA2")
))))
Your Example Code is not good, i think You should have a look at this feed:
http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example
I had to simplify Your code to actually find solution...
Have a look at it:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(id="tabs",
sidebarMenuOutput("menu"))),
dashboardBody(
tabsetPanel(id="tabs2",
tabPanel("Overall",value=1),
tabPanel("Other",value=2))))
server <- function(input, output, session) {
output$menu <- renderMenu({
if (input$tabs2 == 1 ) {
sidebarMenu(
menuItem("TA.Name1", tabName = "TA1"),
menuItem("TA.Name2", tabName = "TA2"))}
else{
sidebarMenu(
menuItem("EA.Name1", tabName = "EA1"),
menuItem("EA.Name2", tabName = "EA2"))
}
})
}
shinyApp(ui = ui, server = server)
It should do what You want -- > reactive sidebarMenu

Resources