How to automatically navigate to another sidebar after data is uploaded in sidebar ?

Hello Shiny dashboard experts,

Following reprex works.
i.e. Once the file is uploaded in sidebar: mod1,
we can navigate to sidebar: mod2 and see the uploaded data displayed
**Can we automate this ?
i.e. Once the data is uploaded in sidebar: mod1,
sidebar: mod2 should be seen to the user with uploaded data.


library(shiny)
library(tidyverse)

# Module UI to read content
mod_readUI <- function(id) {
  ns <- shiny::NS(id)
  shiny::tagList(
    fileInput(ns("file1"), 
              h3("Choose xlsx file"),
              accept=c(".xlsx")),
    actionButton(ns("ref"), "Refresh")
  )
}

# Server modules of reading content
mod_read <- function(input, output, session){
  # Uploaded data as reactive element
  getData <- reactive({
    req(input$file1) # Ensure file is uploaded
    if(!is.null(input$file1)){
      my_data <- readxl::read_excel(input$file1$datapath)
      my_data
    }
    else{
      my_data <- "nothing" %>% as.data.frame()
      my_data
    }
  })
  
  ### In order to pass data as reactive elements to other module:
  # Created list
  reactive({
    # browser()
    list("excl" = getData())
  })
}

# Module UI to display content
mod_displayUI <- function(id) {
  ns <- shiny::NS(id)
  shiny::tagList(
    DT::dataTableOutput(ns("contents"))
  )
}

# Server functions
mod_display <- function(input, output, session, file) {
  output$contents <- DT::renderDataTable({
    req(file())
    DT::datatable(file()$excl,
                  options = list(pageLength = 7,scrollX = TRUE))
  })
}


ui <- 
  shinydashboard::dashboardPage(
    shinydashboard::dashboardHeader(),
    shinydashboard::dashboardSidebar(
      shinydashboard::sidebarMenu(id = "menu1",
                                  shinydashboard::menuItem('mod1',
                                                           tabName = 'mod1', 
                                                           icon = shiny::icon('file')),
                                  
                                  shinydashboard::menuItem('mod2',
                                                           tabName = 'mod2', 
                                                           icon = shiny::icon('file'))
      )),
    shinydashboard::dashboardBody(
      shinydashboard::tabItems(
        shinydashboard::tabItem("mod1",
                                mod_readUI("sidemod1")),
        shinydashboard::tabItem("mod2",
                                mod_displayUI("bodymod2")
        )
      )))

server <- function(input, output) {
  # storing mod_read in a variable
  readFile1 <- shiny::callModule(mod_read, "sidemod1")
  # passing the output of readFile into mod_display module
  displayFile <- shiny::callModule(mod_display, "bodymod2", file = readFile1)
}

shinyApp(ui,server)

I found myself somewhat simplifying your setup before using javascript to control the menu switching. Hope I haven't deviated too much, if you needed those additional abstractions.

library(shiny)
library(tidyverse)
library(shinyjs)
# Module UI to read content
mod_readUI <- function(id) {
  ns <- shiny::NS(id)
  shiny::tagList(
    fileInput(ns("file1"), 
              h3("Choose xlsx file"),
              accept=c(".xlsx")),
    actionButton(ns("ref"), "Refresh")
  )
}

# Server modules of reading content
mod_read <- function(input, output, session){
  # Uploaded data as reactive element

    req(input$file1) # Ensure file is uploaded
    if(!is.null(input$file1)){
      my_data <- readxl::read_excel(input$file1$datapath)
      my_data
    }
    else{
      my_data <- "nothing" %>% as.data.frame()
      my_data
    }

  
}

# Module UI to display content
mod_displayUI <- function(id) {
  ns <- shiny::NS(id)
  shiny::tagList(
    DT::dataTableOutput(ns("contents"))
  )
}

# Server functions
mod_display <- function(input, output, session, file) {
  
  output$contents <- DT::renderDataTable({
    req(file)
    DT::datatable(file,
                  options = list(pageLength = 7,scrollX = TRUE))
  
  
  })
}


ui <- 
  shinydashboard::dashboardPage( 
    shinydashboard::dashboardHeader(),
    shinydashboard::dashboardSidebar(
      shinydashboard::sidebarMenu(id = "menu1",
                                  shinydashboard::menuItem('mod1',
                                                           tabName = 'mod1', 
                                                           icon = shiny::icon('file')),
                                  
                                  shinydashboard::menuItem('mod2',
                                                           tabName = 'mod2', 
                                                           icon = shiny::icon('file'))
      )),
    shinydashboard::dashboardBody(
      shinyjs::useShinyjs(),
      shinydashboard::tabItems(
        shinydashboard::tabItem("mod1",
                                mod_readUI("sidemod1")),
        shinydashboard::tabItem(tabName = "mod2",
                                mod_displayUI("bodymod2"))
        
      )))

server <- function(input, output) {
  # storing mod_read in a variable
  readFile1 <- reactive({shiny::callModule(mod_read, "sidemod1")})
  
  # passing the output of readFile into mod_display module
  shiny::callModule(mod_display, "bodymod2", file = readFile1())
  
  ## additional side effect on readFile1 changing (switch tab)
observeEvent(readFile1(),
             {
               shinyjs::runjs("$('a[data-value=\"mod2\"]').tab('show');")
            })
                 
       
}

shinyApp(ui,server)
1 Like

Thanks for solution.
shinyjs seems to be not used for official work or I didnt understand Mr. Dean V

Can I use this package for office work ?

I'm not a lawyer so I can't advise you on that.
I found that there are documents which describe alternative approach which are I suppose considered core shiny features though it seems it adds more work for a developer that doesnt want to use shinyjs:
https://shiny.rstudio.com/articles/communicating-with-js.html
https://shiny.rstudio.com/articles/js-send-message.html

Thank for those links :slight_smile:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.