1

I have a shiny dashboard with a navbar page which consists of two tabPanels "Summary" and "Available Funds". Then "Available Funds" consists of a tabsetPanel() with two tabPanels "Plot" and "Plot2". When "Plot" is clicked the shiny widget in the right sidebar is displayed. Except from the 1st time that the app is loaded and I click on "Available funds". That happens beacause I have not clicked on "Plot" yet and I wonder how I will connect the navbar tabPanel "Available funds" with the widget display as well.

library(golem)
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)

shinyApp(
  ui = tags$body(class="skin-blue sidebar-mini control-sidebar-open", dashboardPagePlus(
    header = dashboardHeaderPlus(
      enable_rightsidebar = TRUE,
      rightSidebarIcon = "gears"
    ),
    sidebar = dashboardSidebar(),
    body = dashboardBody(
      golem::activate_js(),
      navbarPage("Navbar!",
                 tabPanel("Summary"

                 ),
                 tabPanel("Available funds",
                          tabsetPanel(
                            id="tabA",
                            type = "tabs",
                            tabPanel("Plot"),
                            tabPanel("Plot2"))
                 )), 
      tags$script(
        '$("a[data-toggle=\'tab\']").click(function(){
          Shiny.setInputValue("tabactive", $(this).data("value"))
        })'
      )
    ),
    rightsidebar = rightSidebar(
      background = "dark",
      rightSidebarTabContent(
        id = 1,
        title = "Tab 1",
        icon = "desktop",
        active = TRUE,
        uiOutput("sl")

      )

    ),
    title = "Right Sidebar"
  )),
  server = function(input, output) {
    output$sl <- renderUI({
      req(input$tabactive)
      sliderInput(
        "obs",
        "Number of observations:",
        min = 0, max = 1000, value = 500
      )
    })

    observeEvent( input$tabactive , {
      if (input$tabactive == "Plot"){
        golem::invoke_js("showid", "sl")
      } else {
        golem::invoke_js("hideid", "sl")
      }
    })
  }
)

EDITED VERSION WITH MORE TABPANELS

library(golem)
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)

shinyApp(
  ui = tags$body(class="skin-blue sidebar-mini control-sidebar-open", dashboardPagePlus(
    header = dashboardHeaderPlus(
      enable_rightsidebar = TRUE,
      rightSidebarIcon = "gears"
    ),
    sidebar = dashboardSidebar(),
    body = dashboardBody(
      golem::activate_js(),
      navbarPage("Navbar!",
                 id = "tabactive",
                 tabPanel("Summary",
                          tabsetPanel(
                            id="tabB",
                            type = "tabs",
                            tabPanel("Plot3"),
                            tabPanel("Plot4"))),
                 tabPanel("Available funds",
                          tabsetPanel(
                            id="tabA",
                            type = "tabs",
                            tabPanel("Plot"),
                            tabPanel("Plot2"))
                 ))
    ),
    rightsidebar = rightSidebar(
      background = "dark",
      rightSidebarTabContent(
        id = 1,
        title = "Tab 1",
        icon = "desktop",
        active = TRUE,
        uiOutput("sl")
      )
    ),
    title = "Right Sidebar"
  )),
  server = function(input, output) {
    output$sl <- renderUI({
      req(input$tabactive)
      sliderInput(
        "obs",
        "Number of observations:",
        min = 0, max = 1000, value = 500
      )
    })
    output$sl2 <- renderUI({
      req(input$tabactive)
      sliderInput(
        "obs2",
        "Number of observations:",
        min = 0, max = 100, value = 50
      )
    })
    output$sl3 <- renderUI({
      req(input$tabactive)
      sliderInput(
        "obs3",
        "Number of observations:",
        min = 0, max = 100, value = 50
      )
    })
    output$sl4 <- renderUI({
      req(input$tabactive)
      sliderInput(
        "obs4",
        "Number of observations:",
        min = 0, max = 100, value = 50
      )
    })
    observe({
      if (input$tabactive == "Available funds" && input$tabA == "Plot"){
        golem::invoke_js("showid", "sl")
      } else {
        golem::invoke_js("hideid", "sl")
      }
    })
    observe({
      if (input$tabactive == "Available funds" && input$tabA == "Plot2"){
        golem::invoke_js("showid", "sl2")
      } else {
        golem::invoke_js("hideid", "sl2")
      }
    })
    observe({
      if (input$tabactive == "Summary" && input$tabB == "Plot3"){
        golem::invoke_js("showid", "sl3")
      } else {
        golem::invoke_js("hideid", "sl3")
      }
    })
    observe({
      if (input$tabactive == "Summary" && input$tabB == "Plot4"){
        golem::invoke_js("showid", "sl4")
      } else {
        golem::invoke_js("hideid", "sl4")
      }
    })
  }
)
firmo23
  • 7,490
  • 2
  • 38
  • 114

1 Answers1

1

Please check the following (I simply modified your if-condition):

library(golem)
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)

shinyApp(
  ui = tags$body(class="skin-blue sidebar-mini control-sidebar-open", dashboardPagePlus(
    header = dashboardHeaderPlus(
      enable_rightsidebar = TRUE,
      rightSidebarIcon = "gears"
    ),
    sidebar = dashboardSidebar(),
    body = dashboardBody(
      golem::activate_js(),
      navbarPage("Navbar!",
                 id = "tabactive",
                 tabPanel("Summary"),
                 tabPanel("Available funds",
                          tabsetPanel(
                            id="tabA",
                            type = "tabs",
                            tabPanel("Plot"),
                            tabPanel("Plot2"))
                 ))
    ),
    rightsidebar = rightSidebar(
      background = "dark",
      rightSidebarTabContent(
        id = 1,
        title = "Tab 1",
        icon = "desktop",
        active = TRUE,
        uiOutput("sl")
      )
    ),
    title = "Right Sidebar"
  )),
  server = function(input, output) {
    output$sl <- renderUI({
      sliderInput(
        "obs",
        "Number of observations:",
        min = 0, max = 1000, value = 500
      )
    })

    observe({
      if (input$tabactive == "Available funds" && input$tabA == "Plot"){
        golem::invoke_js("showid", "sl")
      } else {
        golem::invoke_js("hideid", "sl")
      }
    })
  }
)

Btw. you don't need that JS code to get input$tabactive since navbarPage also has an id argument.


Another way is wrapping uiOutput("sl") in conditionalPanel like this:

library(golem)
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)

shinyApp(
  ui = tags$body(class="skin-blue sidebar-mini control-sidebar-open", dashboardPagePlus(
    header = dashboardHeaderPlus(
      enable_rightsidebar = TRUE,
      rightSidebarIcon = "gears"
    ),
    sidebar = dashboardSidebar(),
    body = dashboardBody(
      golem::activate_js(),
      navbarPage("Navbar!",
                 id = "tabactive",
                 tabPanel("Summary"),
                 tabPanel("Available funds",
                          tabsetPanel(
                            id="tabA",
                            type = "tabs",
                            tabPanel("Plot"),
                            tabPanel("Plot2"))
                 ))
    ),
    rightsidebar = rightSidebar(
      background = "dark",
      rightSidebarTabContent(
        id = 1,
        title = "Tab 1",
        icon = "desktop",
        active = TRUE,
        conditionalPanel(condition = "input.tabactive == 'Available funds' && input.tabA == 'Plot'", {uiOutput("sl")})
      )
    ),
    title = "Right Sidebar"
  )),
  server = function(input, output) {
    output$sl <- renderUI({
      sliderInput(
        "obs",
        "Number of observations:",
        min = 0, max = 1000, value = 500
      )
    })
  }
)

After OPs edit:

library(golem)
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)

shinyApp(
  ui = tags$body(class="skin-blue sidebar-mini control-sidebar-open", dashboardPagePlus(
    header = dashboardHeaderPlus(
      enable_rightsidebar = TRUE,
      rightSidebarIcon = "gears"
    ),
    sidebar = dashboardSidebar(),
    body = dashboardBody(
      golem::activate_js(),
      navbarPage("Navbar!",
                 id = "tabactive",
                 tabPanel("Summary",
                          tabsetPanel(
                            id="tabB",
                            type = "tabs",
                            tabPanel("Plot3"),
                            tabPanel("Plot4"))),
                 tabPanel("Available funds",
                          tabsetPanel(
                            id="tabA",
                            type = "tabs",
                            tabPanel("Plot"),
                            tabPanel("Plot2"))
                 ))
    ),
    rightsidebar = rightSidebar(
      background = "dark",
      rightSidebarTabContent(
        id = 1,
        title = "Tab 1",
        icon = "desktop",
        active = TRUE,
        uiOutput("sl"),
        uiOutput("sl2"),
        uiOutput("sl3"),
        uiOutput("sl4")
      )
    ),
    title = "Right Sidebar"
  )),
  server = function(input, output) {
    output$sl <- renderUI({
      req(input$tabactive)
      sliderInput(
        "obs",
        "Number of observations:",
        min = 0, max = 1000, value = 500
      )
    })
    output$sl2 <- renderUI({
      req(input$tabactive)
      sliderInput(
        "obs2",
        "Number of observations:",
        min = 0, max = 100, value = 50
      )
    })
    output$sl3 <- renderUI({
      req(input$tabactive)
      sliderInput(
        "obs3",
        "Number of observations:",
        min = 0, max = 100, value = 50
      )
    })
    output$sl4 <- renderUI({
      req(input$tabactive)
      sliderInput(
        "obs4",
        "Number of observations:",
        min = 0, max = 100, value = 50
      )
    })
    observe({
      if (input$tabactive == "Available funds" && input$tabA == "Plot"){
        golem::invoke_js("showid", "sl")
      } else {
        golem::invoke_js("hideid", "sl")
      }
    })
    observe({
      if (input$tabactive == "Available funds" && input$tabA == "Plot2"){
        golem::invoke_js("showid", "sl2")
      } else {
        golem::invoke_js("hideid", "sl2")
      }
    })
    observe({
      if (input$tabactive == "Summary" && input$tabB == "Plot3"){
        golem::invoke_js("showid", "sl3")
      } else {
        golem::invoke_js("hideid", "sl3")
      }
    })
    observe({
      if (input$tabactive == "Summary" && input$tabB == "Plot4"){
        golem::invoke_js("showid", "sl4")
      } else {
        golem::invoke_js("hideid", "sl4")
      }
    })
  }
)

Here is a UI-only solution:

library(golem)
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)

shinyApp(
  ui = tags$body(class="skin-blue sidebar-mini control-sidebar-open", dashboardPagePlus(
    header = dashboardHeaderPlus(
      enable_rightsidebar = TRUE,
      rightSidebarIcon = "gears"
    ),
    sidebar = dashboardSidebar(),
    body = dashboardBody(
      golem::activate_js(),
      navbarPage("Navbar!",
                 id = "tabactive",
                 tabPanel("Summary",
                          tabsetPanel(
                            id="tabB",
                            type = "tabs",
                            tabPanel("Plot3"),
                            tabPanel("Plot4"))),
                 tabPanel("Available funds",
                          tabsetPanel(
                            id="tabA",
                            type = "tabs",
                            tabPanel("Plot1"),
                            tabPanel("Plot2"))
                 ))
    ),
    rightsidebar = rightSidebar(
      background = "dark",
      rightSidebarTabContent(
        id = 1,
        title = "Tab 1",
        icon = "desktop",
        active = TRUE,
        conditionalPanel(condition = "input.tabactive == 'Available funds' && input.tabA == 'Plot1'", {
          sliderInput(
            "obs1",
            "Number of observations 1:",
            min = 0, max = 1000, value = 500
          )}),
        conditionalPanel(condition = "input.tabactive == 'Available funds' && input.tabA == 'Plot2'", {
          sliderInput(
            "obs2",
            "Number of observations 2:",
            min = 0, max = 100, value = 50
          )}),
        conditionalPanel(condition = "input.tabactive == 'Summary' && input.tabB == 'Plot3'", {
          sliderInput(
            "obs3",
            "Number of observations 3:",
            min = 0, max = 100, value = 50
          )}),
        conditionalPanel(condition = "input.tabactive == 'Summary' && input.tabB == 'Plot4'", {
          sliderInput(
            "obs4",
            "Number of observations 4:",
            min = 0, max = 100, value = 50
          )})
      )
    ),
    title = "Right Sidebar"
  )),
  server = function(input, output) {}
)
ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
  • I like your approaches but when I tried to add more panels and widgets it did not respond accordingly as you can see in my edit. Is there a way to do this without depending on the click button? There will be many panels in my actual app. I mean depending only on the ids. – firmo23 Nov 19 '19 at 14:34
  • wait I missed sth – firmo23 Nov 19 '19 at 14:45
  • You didn't assign the uiOutputs: `uiOutput("sl2"), uiOutput("sl3"), uiOutput("sl4")`. Please see my edit. – ismirsehregal Nov 19 '19 at 15:00
  • all your approaches work here but when I try to adapt them to my app the widgets aare displayed only when I the navbar panel is the last button I have clicked on – firmo23 Nov 19 '19 at 16:34
  • Any `req(input$tabactive)` left in the code which shouldn't be there? – ismirsehregal Nov 19 '19 at 17:38
  • no this is very strange it seems like everything depends on clicking the navbar panel or not – firmo23 Nov 19 '19 at 17:47
  • if we have ids why even js is necessary? ..a simple if with both conditions fullfilled should have been enough – firmo23 Nov 19 '19 at 17:55
  • The first approach I sent is based on a simple if-clause. – ismirsehregal Nov 19 '19 at 18:22
  • I think the problem was that I was including the tags$script with the js code and the tabactive – firmo23 Nov 19 '19 at 18:57
  • Ah okay, yes assigning the id twice might result in strange behaviour. So now you've got it working as expected? – ismirsehregal Nov 19 '19 at 20:12
  • @ismirsehregal - I have a huge favor to you- can you please help me with this question: https://stackoverflow.com/questions/75453946/why-i-do-not-get-my-data-under-the-load-data-panel – GaB Feb 15 '23 at 00:45
  • @GaB sorry I'm not familiar with {golem}. – ismirsehregal Feb 15 '23 at 07:38