shiny: start the app with hidden tabs, with NO delay

前端 未结 4 1335
一个人的身影
一个人的身影 2020-12-15 13:24

I would like to build an application and some of the tabs will be hidden to the user until he types the right password. I know how to do this with shinyjs::hideTab

相关标签:
4条回答
  • 2020-12-15 13:53

    I solved this problem creating a new function (above the UI definition) to include the style="display:none; on the right li tags:

    tabsethidepanels<-function(tag, indexes = NULL) {
      if (class(tag) == "shiny.tag" && tag$name == "div" && tag$attribs$class == "tabbable") {
        if (is.null(indexes)) indexes<-seq_along(tag$children[[1]]$children[[1]])
        for (i in indexes) tag$children[[1]]$children[[1]][[i]]$attribs<-c(tag$children[[1]]$children[[1]][[i]]$attribs, list(style="display:none;"))
        tag
      } else stop("tag must be a tabsetPanel!", call. = F)
    }
    

    And define the tabset accordingly:

    tabsethidepanels(
      tabsetPanel(
        id = "mytab",
        selected = "tab7-not2hide",
        tabPanel("tab1"),
        tabPanel("tab2"),
        tabPanel("tab3"),
        tabPanel("tab4"),
        tabPanel("tab5"),
        tabPanel("tab6"),
        tabPanel("tab7-not2hide")
      ),
      indexes = 1:6
    )
    

    The "indexes" field are usefull to select only the right tabs to hide:

    <div class="tabbable">
      <ul class="nav nav-tabs shiny-tab-input" id="mytab" data-tabsetid="2818">
        <li style="display:none;">
          <a href="#tab-2818-1" data-toggle="tab" data-value="tab1">tab1</a>
        </li>
        <li style="display:none;">
          <a href="#tab-2818-2" data-toggle="tab" data-value="tab2">tab2</a>
        </li>
        <li style="display:none;">
          <a href="#tab-2818-3" data-toggle="tab" data-value="tab3">tab3</a>
        </li>
        <li style="display:none;">
          <a href="#tab-2818-4" data-toggle="tab" data-value="tab4">tab4</a>
        </li>
        <li style="display:none;">
          <a href="#tab-2818-5" data-toggle="tab" data-value="tab5">tab5</a>
        </li>
        <li style="display:none;">
          <a href="#tab-2818-6" data-toggle="tab" data-value="tab6">tab6</a>
        </li>
        <li class="active">
          <a href="#tab-2818-7" data-toggle="tab" data-value="tab7-not2hide">tab7-not2hide</a>
        </li>
      </ul>
      <div class="tab-content" data-tabsetid="2818">
        <div class="tab-pane" data-value="tab1" id="tab-2818-1"></div>
        <div class="tab-pane" data-value="tab2" id="tab-2818-2"></div>
        <div class="tab-pane" data-value="tab3" id="tab-2818-3"></div>
        <div class="tab-pane" data-value="tab4" id="tab-2818-4"></div>
        <div class="tab-pane" data-value="tab5" id="tab-2818-5"></div>
        <div class="tab-pane" data-value="tab6" id="tab-2818-6"></div>
        <div class="tab-pane active" data-value="tab7-not2hide" id="tab-2818-7"></div>
      </div>
    </div>
    

    Remember to select a tab not to hide as active selected = "tab7-not2hide".

    If you need to hide all tabs I sugest to create a "blank" tabPanel, select his one as active and hide all tabs with indexes = NULL.

    0 讨论(0)
  • 2020-12-15 13:55

    How about this

    library(shiny);library(shinyjs)
    ui <- fluidPage(useShinyjs(),
                    navbarPage("hello", id="hello",
                               tabPanel("home", br(), h3("this is home"),passwordInput("pass", "enter 'password' to see the tabs: "),actionButton("enter", "enter")),
                               tabPanel("tab2",uiOutput("tab2Content")),
                               tabPanel("tab3 with a lot of stuff in it", uiOutput("tab3Content"))))
    server <- function(input, output, session) {
      output$tab2Content <- renderUI({
        req(input$pass == "password")
        tagList(
          br(), 
          h4("this is tab2")
        )
      })
      output$tab3Content <- renderUI({
        req(input$pass == "password")
        tagList(
          br(), 
          h4("this is tab3")
        )
      })}
    shinyApp(ui, server)
    

    hope this helps!

    0 讨论(0)
  • 2020-12-15 14:05

    You could use javascript with extendShinyjs() to hide the tabs you want on page load:

    Javascript code:

    shinyjs.init = function(){
      $('#hello li a[data-value="tab3_val"]').hide();
      $('#hello li a[data-value="tab2_val"]').hide();
    }
    

    R code:

    ui <- fluidPage(useShinyjs(),
                    #Added this js
                    extendShinyjs(script = path_to_javascript_file),
                    navbarPage("hello", id="hello",
                               tabPanel("home", br(), h3("this is home"),passwordInput("pass", "enter 'password' to see the tabs: "),actionButton("enter", "enter")),
                               tabPanel("tab2", value = "tab2_val", br(), h4("this is tab2")),
                               tabPanel("tab3 with a lot of stuff in it", value = "tab3_val", br(), h4("this is tab3"))))
    
    server <- function(input, output, session) {
    
      observeEvent(input$enter, {
        if (input$pass == "password"){
          show(selector = '#hello li a[data-value="tab3_val"]')
          show(selector = '#hello li a[data-value="tab2_val"]')
          }})}
    shinyApp(ui, server)
    

    Alternatively the CSS actually isn't too complicated. If you wanted to go that route you could simply replace the extendShinyjs() call in the above with:

    tags$head(tags$style(HTML("#hello li a[data-value = 'tab2_val'], #hello li a[data-value = 'tab3_val'] {
                                 display: none;
     }")))
    

    The downside to this is that the formatting of the tabs appears to be off after un-hiding them.

    0 讨论(0)
  • 2020-12-15 14:05

    I'd go with renderUI (see @BertilBaron's answer) or appendTab because it's easy to bypass the password when hiding the tabs:

    Here is how to achive the desired behaviour via appendTab avoiding the above with basic shiny, no additional JS:

    library(shiny)
    
    ui <- fluidPage(navbarPage("hello", id = "hello",
      tabPanel(
        "home",
        br(),
        h3("this is home"),
        passwordInput("pass", "enter 'password' to see the tabs: "),
        actionButton("enter", "enter")
      )
    ))
    
    server <- function(input, output, session) {
      observeEvent(input$enter, {
        if (input$pass == "password") {
          appendTab(inputId = "hello", tab = tabPanel("tab2", value = "tab2_val", br(), h4("this is tab2")))
          appendTab(inputId = "hello", tab = tabPanel("tab3 with a lot of stuff in it",value = "tab3_val", br(), h4("this is tab3")))
        }
      })
    }
    
    shinyApp(ui, server)
    
    0 讨论(0)
提交回复
热议问题