Shiny how to block the user from accessing a tab?

Viewed 327

I need to block the user from accessing to other tabs until certain actions are fulfilled. In this reproducible example, I want to block the user to access the Tab 2 until he pressed the button.

This is how the app looks:

enter image description here

Here's the code for the app:

library(shiny)

ui <- shinyUI(navbarPage("",
                         tabPanel(h1("Tab1"), value = "nav1",
                                  mainPanel(
                                            br(),
                                            h2("The user must press this button to access the other tab."),
                                            br(),
                                            shiny::actionButton('button', 'press the button')
                                  )
                         ),
                         tabPanel(h1("Tab2"),
                                  value = "nav2",

                                  h3('Block access until user presses button')
                         )
)
)

server <- shinyServer(function(input, output) {


})

# Run the application
shinyApp(ui = ui, server = server)


I would like the user to be able to see that Tab2 exists, but make it unclickable until they press the button.

Any ideas?

3 Answers
  1. There is no need of using any server side processing. One of the modern web app development concepts is front-end and back-end separation. If you can do it on front-end, then don't use server to do the job.
  2. conditionalPanel is a better solution but users can still click the tab button, just give them an empty page.

Here is an even better solution, let's use some js to disable the tab button unless users click the action button. Users can see the tab button but it's gray and unclickable on start:

library(shiny)

ui <- shinyUI(navbarPage(
  "",
  tabPanel(
    h1("Tab1"), 
    value = "nav1",
    mainPanel(
      br(),
      h2("The user must press this button to access the other tab."),
      br(),
      shiny::actionButton('button', 'press the button', onclick = "$(tab).removeClass('disabled')")
    )
  ),
  tabPanel(
    h1("Tab2"),
    value = "nav2",
    uiOutput("tab2contents")
  ),
  tags$script(
    '
    var tab = $(\'a[data-value="nav2"]\').parent().addClass("disabled");
    $(function(){
      $(tab.parent()).on("click", "li.disabled", function(e) {
        e.preventDefault();
        return false;
      });
    });
    '
  )
))    

server <- shinyServer(function(input, output) {

})

# Run the application
shinyApp(ui = ui, server = server)

enter image description here

Use conditionalPanel(). Condition? The button shouldn't have zero clicks.

Your example now becomes:

library(shiny)

ui <- shinyUI(
  navbarPage(
    title = "", 
    
    tabPanel(
      title = h1("Tab1"), 
      value = "nav1",
      
      mainPanel(
        br(),
        h2("The user must press this button to access the other tab."),
        br(),
        shiny::actionButton('button', 'press the button')
      )
    ), 
    
    tabPanel(
      h1("Tab2"),
      value = "nav2",
      
      # ----conditional panel here----
      conditionalPanel(
        condition = "input.button != 0", 
        
        h3('Block access until user presses button')
      )
    )
  )
)

server <- shinyServer(function(input, output) {
  
  
})

# Run the application
shinyApp(ui = ui, server = server)

Adding detail to my comment above:

library(shiny)

ui <- shinyUI(navbarPage("",
        tabPanel(
          h1("Tab1"), 
          value = "nav1",
          mainPanel(
            br(),
            h2("The user must press this button to access the other tab."),
            br(),
            shiny::actionButton('button', 'press the button')
          )
        ),
        tabPanel(
          h1("Tab2"),
          value = "nav2",
          uiOutput("tab2contents")
        )
      )
    )    

server <- shinyServer(function(input, output) {
   v <- reactiveValues(tab2Active=FALSE)
   
  observeEvent(input$button, { v$tab2Active <- TRUE})

  output$tab2contents <- renderUI({
    if (v$tab2Active) {
      h3('Tab 2 is active')
    } else {
      h3('Block access until user presses button')
    }
  })
})

# Run the application
shinyApp(ui = ui, server = server)
Related