7
votes

I am using R/shinydasboard to create a web app that I am putting behind a login screen.

I'm having trouble with getting the main body to render based on the sidebar menu tabs.

I've tried to ensure one of the tab items has selected = TRUE still to no avail.

Sample code below:

require(shiny)
require(shinydashboard)

Logged <- FALSE;
LoginPass <- 0; #0: not attempted, -1: failed, 1: passed

login <- box(title = "Login",textInput("userName", "Username (user)"),
             passwordInput("passwd", "Password (test)"),
             br(),actionButton("Login", "Log in"))

loginfail <- box(title = "Login",textInput("userName", "Username"),
                 passwordInput("passwd", "Password"),
                 p("Username or password incorrect"),
                 br(),actionButton("Login", "Log in"))

mainbody <- div(tabItems(
  tabItem(tabName = "t_item1", box(title = "Item 1 information")),
  tabItem(tabName = "t_item2", box(title = "Item 2 information")),
  tabItem(tabName = "t_item3", box(title = "Item 3 information"))
)
)

header <- dashboardHeader(title = "dashboard header")

sidebar <- dashboardSidebar(uiOutput("sidebarpanel"))

body <- dashboardBody(uiOutput("body"))

ui <- dashboardPage(header, sidebar, body)

server <- function(input, output, session) {
  USER <<- reactiveValues(Logged = Logged, LoginPass = LoginPass)
  observe({
    if (USER$Logged == FALSE) {
      if (!is.null(input$Login)) {
        if (input$Login > 0) {
          username <- isolate(input$userName)
          password <- isolate(input$passwd)
          #Id.username <- which(my_username == Username)
          if (username == "user" & password == "test") {
            USER$Logged <<- TRUE
            USER$LoginPass <<- 1
          }
          USER$LoginPass <<- -1
        }
      }
    }
  })

  output$sidebarpanel <- renderUI({
    if (USER$Logged == TRUE) {
      div(
        sidebarMenu(
          menuItem("Item 1", tabName = "t_item1", icon = icon("line-chart"), selected = TRUE),
          menuItem("Item 2", tabName = "t_item2", icon = icon("users")),
          menuItem("item 3", tabName = "t_item3", icon = icon("dollar"))
        )
      )}
  })
  output$body <- renderUI({
    if (USER$Logged == TRUE) {
      mainbody
    }
    else {
      if(USER$LoginPass >= 0) {
        login
      }
      else {
        loginfail
      }
    }
  })
}

shinyApp(ui, server)

Any suggestions on how to get the mainbody to show one of the tabs when it loads would be greatly appreciated. I have a suspicion it may due to the load order of the sidebar and the body however I am not sure how to investigate further.

I have also tried a conditionalPanel however couldn't get that to work either.

UPDATE This screenshot shows the behaviour that occurs straight after login. Current screen after login

This screenshot shows the desired behaviour after login.Desired screen after login

1
This does work for me, have you tried updating your packages and if you're using Rstudio doing the old classic shutdown and start? - RmIu
The code works, however it doesn't select the first menu item. Have updated the post with screenshots. - Dan
This is nice. I'm trying to 'read' the body from another R file with source(mybody.r, but it doesn't work. Any ideas on this? If this is not clear I can provide an example. - Tim_Utrecht
@Tim_Utrecht try using source(mybody.r, local = TRUE) - Dan

1 Answers

6
votes

You need to set the tabItem as active:

tabItem(tabName = "t_item1", class = "active", box(title = "Item 1 information"))

It will render the first tab when you dynamically render the content after login.