I would like to hide/show a tabpanel given certain conditions. When selecting "source 2", I would like to hide tab2, but the code that I used have a bug.
If I first selected "source 1", and then clicked "tab2", and changed the data source to "source 2", the "tab2" tabpanel indeed hided, but the content of "tab2" covered the contents of "tab1". How can I remove the resudual of the hided tab? Any thoughts would be highly appreciated.
library(shiny)
library(shinyjs)
runApp(list(
ui = fluidPage(
useShinyjs(),
selectInput('dataSource',h5("Please choose the data source:"), c("source 1", "source 2"), "source 1"),
tabsetPanel(
id = "navbar",
tabPanel(title = "tab1",
value = "tab1",
h1("Tab 1")
),
tabPanel(id="id2", title = "tab2",
value = "tab2",
h1("Tab 2")
)
)
),
server = function(input, output) {
observeEvent(input$dataSource,{
toggle(condition = (input$dataSource !='source 2'), selector = "#navbar li a[data-value=tab2]")
})
}
))
[the bug looks like this][1] [1]: http://i.stack.imgur.com/eOHLS.png
I could reproduce the error on my laptop.
My advice would be to use a renderUI function to create dynamically a tabsetPanel.
library(shiny)
# library(shinyjs)
runApp(list(
ui = fluidPage(
#useShinyjs(),
selectInput('dataSource',h5("Please choose the data source:"), c("source 1", "source 2"), "source 1"),
uiOutput("dynamic")
),
server = function(input, output) {
output$dynamic <- renderUI({
if (input$dataSource == "source 1") {
tabsetPanel(
id = "navbar",
tabPanel(title = "tab1",
value = "tab1",
h1("Tab 1")
),
tabPanel(id="id2", title = "tab2",
value = "tab2",
h1("Tab 2")
)
)
} else {
tabsetPanel(
id = "navbar",
tabPanel(title = "tab1",
value = "tab1",
h1("Tab 1")
)
)
}
})
}
))
Related
The following code creates and h3 tab header, a picker input and 2 action buttons inside a class of page-header. The action buttons and slightly elevated compared to the picker input. I would like to get the action buttons to be horizontally aligned with the picker input (see red boxes in the screenshot).
How can I adjust this code to make it work.
library(shiny)
ui <- fluidPage(
div(
class = "page-header",
fluidRow(
column(
width = 8,
h3("Tab Header")
),
column(
width = 2,
pickerInput(
inputId = "picker",
label = "Picker:",
choices = c("Option 1", "Option 2", "Option 3")
)
),
column(
width = 2,
actionButton(inputId = "apply_1",
label = "Action 1",
icon = icon("play")),
actionButton(inputId = "reset_1",
label = "Action 2",
icon = icon("sync"))
)
)
)
)
server <- function(input, output) {
}
shinyApp(ui, server)
One option to horizontally align the pickerInput with the actionButtons would be to mimic the tag structure of the pickerInput, which looks like so:
<div>
<label>...</label>
<div>
....
</div>
</div>
For the label I added an invisible label by setting the color to transparent but there are probably more elegant approaches.
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
div(
class = "page-header",
fluidRow(
column(
width = 8,
h3("Tab Header")
),
column(
width = 2,
pickerInput(
inputId = "picker",
label = "Picker:",
choices = c("Option 1", "Option 2", "Option 3")
)
),
column(
width = 2,
tags$div(
tags$label("Actions:", style="color: transparent"),
tags$div(
actionButton(
inputId = "apply_1",
label = "Action 1",
icon = icon("play")
),
actionButton(
inputId = "reset_1",
label = "Action 2",
icon = icon("sync")
)
)
)
)
)
)
)
server <- function(input, output) {
}
shinyApp(ui, server)
I have this code:
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
shinyApp(
ui = dashboardPage(
header = dashboardHeader(userOutput("user")),
sidebar = dashboardSidebar(shinyjs::useShinyjs(),uiOutput("sidebarpanel")),
body = dashboardBody(uiOutput("body")),
title = "DashboardPage"
),
server = function(input, output) {
output$user <- renderUser({
dashboardUser(
name = "Divad Nojnarg",
image = "https://adminlte.io/themes/AdminLTE/dist/img/user2-160x160.jpg",
title = "shinydashboardPlus",
subtitle = "Author",
footer = p("The footer", class = "text-center"),
fluidRow(
actionButton("personalInfo","Personal Info")
)
)
})
observeEvent(input$personalInfo, {
output$body <- renderUI({h4("Personal Info Dahsboard (no menuItem)")})
})
output$sidebarpanel <- renderUI({
sidebarMenu(id="tabs",
menuItem("Dashboard 1", tabName = "dashboard1", icon = icon("dashboard"))
,menuItem("Dashboard 2", tabName = "dashboard2", icon = icon("dashboard"))
)
})
output$body <- renderUI({
tabItems(
tabItem(tabName ="dashboard1",
fluidRow(box(width = 12, h4("Dashboard 1 (menuItem)"))))
,tabItem(tabName ="dashboard2",
fluidRow(box(width = 12, h4("Dashboard 2 (menuItem)"))))
)
})
}
)
I would like to do two things:
First: When I click on "Personal Info" button, then, prevent the menuItem to be shadowed (I assume I need to remove the class "selected" or "active" or something like that)
Second: I want to fix this: After pressing "Personal Info" button, the menuItems do not work:
As already shown in my earlier answer here we can use a hidden menuItem to modify the body content independent from the visibly selected menuItem.
Furthermore, I'd recommend to stop using renderUI in this scenario. In general it is slower to re-render a UI element instead of updating an existing element (here we can switch to the hidden menuItem via updateTabItems - however, this applies also to e.g. using updateSelectInput instead of renderUI({selectInput(...)})). In this context you should also question whether you really need the to create the dashboardUser on the server side.
If you really need a server side generated dashboardSidebar you still should not use renderUI - There are the renderMenu() / sidebarMenuOutput() functions available for this. Please see the related docs here.
library(shiny)
library(shinyjs)
library(shinydashboard)
library(shinydashboardPlus)
shinyApp(
ui = dashboardPage(
header = dashboardHeader(userOutput("user")),
sidebar = dashboardSidebar(shinyjs::useShinyjs(),
sidebarMenu(id="tabs",
menuItem("Tab 1", tabName = "tab1", icon = icon("dashboard")),
menuItem("Tab 2", tabName = "tab2", icon = icon("dashboard")),
hidden(menuItem("Personal Tab", tabName = "personal_tab", icon = icon("dashboard")))
)),
body = dashboardBody(useShinyjs(),
tabItems(
tabItem(tabName ="tab1",
fluidRow(box(width = 12, h4("Tab 1 (menuItem)")))),
tabItem(tabName ="tab2",
fluidRow(box(width = 12, h4("Tab 2 (menuItem)")))),
tabItem(tabName ="personal_tab",
fluidRow(box(width = 12, h4("Personal Info Dahsboard (no menuItem)"))))
)
),
title = "DashboardPage"
),
server = function(input, output, session) {
output$user <- renderUser({
dashboardUser(
name = "Divad Nojnarg",
image = "https://adminlte.io/themes/AdminLTE/dist/img/user2-160x160.jpg",
title = "shinydashboardPlus",
subtitle = "Author",
footer = p("The footer", class = "text-center"),
fluidRow(
actionButton("personalInfo","Personal Info")
)
)
})
observeEvent(input$personalInfo, {
shinydashboard::updateTabItems(session, inputId = "tabs", selected = "personal_tab")
})
}
)
Lets take the example of the reference: https://rstudio.github.io/shinydashboard/structure.html#sidebar-menu-items-and-tabs. When put more items in the menuItem(), your associate tab don't works anymore. I tried in this simple modification in example below and just shown the widgets' tab:
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Dashboard",
tabName = "dashboard",
icon = icon("dashboard"),
selected = TRUE,
startExpanded = TRUE,
numericInput("num1",
"Put the First Number",
value = 1,
min = 0),
numericInput("num2",
"Put the Second Number",
value = 1,
min = 0)
),
menuItem("Widgets",
icon = icon("th"),
tabName = "widgets")
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
h2("Dashboard tab content"),
fluidRow(
valueBoxOutput("box1", width = 6),
valueBoxOutput("box2", width = 6)
)
),
tabItem(tabName = "widgets",
h2("Widgets tab content")
)
)
)
# Put them together into a dashboardPage
ui <- dashboardPage(
skin = "green",
dashboardHeader(title = "Example"),
sidebar,
body
)
server <- function(input, output){
output$box1 <- renderValueBox({
valueBox(input$num1,
"First Number",
color = "aqua",
icon = icon("chart-line"))
})
output$box2 <- renderValueBox({
valueBox(input$num2,
"Second Number",
color = "aqua",
icon = icon("chart-line"))
})
}
shinyApp(ui, server)
That is because childfull menuItem behaves differently as noted here. Therefore, you need to define a menuItem or a menSubItem within that dashboard page so that your desired content can be displayed.
Try this
sidebarMenu(id = "tabs",
menuItem("Dashboard",
tabName = "dashboard",
icon = icon("tachometer-alt"),
selected = TRUE,
startExpanded = TRUE,
#icon = icon(fontawesome:::fa_tbl[[1]][505]),
menuItem("Sub-item 1", tabName = "subitem1"),
### menuSubItem("Sub-item 1", tabName = "subitem1"), ## it can be menuSubItem instead of menuItem
numericInput("num1",
"Put the First Number",
value = 1,
min = 0),
numericInput("num2",
"Put the Second Number",
value = 2,
min = 0)
),
menuItem("Widgets",
icon = icon("th"),
tabName = "widgets")
)
)
body <- shinydashboard::dashboardBody(
tabItems(
tabItem(tabName = "subitem1",
h2("Sub item1 tab content in Dashboard"),
fluidRow(
valueBoxOutput("box1", width = 6),
valueBoxOutput("box2", width = 6)
)
),
tabItem(tabName = "widgets",
h2("Widgets tab content")
)
)
)
# Put them together into a dashboardPage
ui <- shinydashboard::dashboardPage(
skin = "green",
shinydashboard::dashboardHeader(title = "Example"),
sidebar,
body
)
server <- function(input, output, session){
output$box1 <- renderValueBox({
valueBox(input$num1,
"First Number",
color = "aqua",
icon = icon("chart-line"))
})
output$box2 <- renderValueBox({
valueBox(input$num2,
"Second Number",
color = "aqua",
icon = icon("chart-line"))
})
observe({print(input$tabs)})
}
shinyApp(ui, server)
Is there a way to trigger the tab only when the user clicks on action button . Example shown below. So tab2 is hidden, but when the user clicks on action button, the tab should pop up
library(shiny)
ui <- fluidPage(
tabsetPanel(id = "tabs",
tabPanel(value = "tab1", title = "Tab 1",
tableOutput("myTable"),
actionButton("sub","Submit")
),
uiOutput("show_tab1")
# tabPanel(value = "tab2", title = "Tab 2",
# plotOutput("myPlot")
# )
)
)
server <- function(input, output, session) {
observeEvent(input$sub,{
output$show_tab1 <- renderUI({
tabPanel(value = "tab2", title = "Tab 2",
plotOutput("myPlot")
)
})
})
}
shinyApp(ui, server)
Maybe this:
library(shiny)
ui <- fluidPage(
tabsetPanel(id = "tabs",
tabPanel(value = "tab1", title = "Tab 1",
tableOutput("myTable"),
actionButton("sub","Submit")
),
tabPanel(value = "tab2", title = "Tab 2",plotOutput("myPlot"))
)
)
server <- function(input, output, session) {
observe({
hideTab(inputId = "tabs", target = "tab2")
})
observeEvent(input$sub,{
showTab(inputId = "tabs", target = "tab2")
})
}
shinyApp(ui, server)
I'm trying to dynamically show/hide tabPanels inside a shiny "modal" in my app but I cant work it out. If I use my current code and simply put the tabPanels inside the main body of the app, the code works just fine so it seems like somehow the app does not recognize that it has to show/hid panels inside the modal.
library(shiny)
tabPanel_modal<-function() {
modalDialog(
tabsetPanel(
id = "available_tabs",
tabPanel(
title = "Tab A",
value = "tab_a"
),
tabPanel(
title = "Tab B",
value = "tab_b"
),
tabPanel(
title = "Tab C",
value = "tab_c"
)
)
,
size = "l",
footer = tagList(
modalButton("Close")
)
)
}
ui <- shinyUI(
fluidPage(
checkboxGroupInput(
inputId = "tab_selections",
label = "select tabs to include in the modal",
choiceNames = list("Tab A",
"Tab B",
"Tab C"
),
choiceValues = c("a","b","c")
),
actionButton("start_modal","Start modal")
)
)
server <- shinyServer(function(input,output,session){
observeEvent(input$start_modal,{
showModal(tabPanel_modal())
})
observe({
hideTab(inputId = "available_tabs", target = "tab_a")
hideTab(inputId = "available_tabs", target = "tab_b")
hideTab(inputId = "available_tabs", target = "tab_c")
})
observeEvent(input$start_modal, {
if ("a" %in% input$tab_selections){
showTab(inputId = "available_tabs", target = "tab_a")
}
if ("b" %in% input$tab_selections){
showTab(inputId = "available_tabs", target = "tab_b")
}
if ("c" %in% input$tab_selections){
showTab(inputId = "available_tabs", target = "tab_c")
}
})
})
shinyApp(ui = ui, server = server)