rshinyshinyjsbslib

Can't get shinyjs to work in bslib dashboard


I'm sure that my placement of useShinyJS() is incorrect, but I have tried multiple locations and I just can't get it to work. In the code below, when hitting "Run" it should hide() two elements for 10 seconds and then make them visible again. Nothing is happening, and it is because of the placement, where should I place useShinyJS()?

library(shiny)
library(shinyWidgets)
library(shinyjs)
library(bslib)
library(DT)

mod_ui <- function(id){
  ns <- NS(id)
  tagList(
    useShinyjs(),
  layout_sidebar(
    sidebar = sidebar(
      div(id = "b", pickerInput(ns("test_button"), choices = c("A", "B", "C"))),
      actionButton(ns("generate_graphs"), "Run")
    ),
    
    div(id = "a", card(DTOutput(NS(id, "table_mainpanel"))))
    
    
    
    
  )
    )
  
}

mod_server <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      
      observeEvent(input$generate_graphs,
                   {
        
        print("Hiding")
        
        shinyjs::hide(id = "a")
        shinyjs::hide(id = "b")
        
        print("Sleeping")
        Sys.sleep(10)
        shinyjs::show(id = "a")
        shinyjs::show(id = "b")
        print("Done")
        
        
        
      })
      
    }
    
  )}
  
  app <- function(){
    
    ui <- page_fluid(
      page_navbar(
        title = "Test",
        collapsible = TRUE,
        id = "navbar",
        fillable = "Dashboard",
        
        
        nav_menu(
          'Data section',
          
          
          nav_panel('Upload Data', mod_ui("upload_data")),
        )))
    
    server <- function(session, input, output){
      
      mod_server("upload_data")

      
    }
    
    shinyApp(ui, server)
    
  }
  
app()
          
      
      
      

Solution

  • You will need to set the asis parameter to TRUE for shinyjs::hide and shinyjs::show when used in a module:

    library(shiny)
    library(shinyWidgets)
    library(shinyjs)
    library(bslib)
    library(DT)
    
    mod_ui <- function(id) {
      ns <- NS(id)
      tagList(layout_sidebar(sidebar = sidebar(
        div(id = "b", pickerInput(
          ns("test_button"), choices = c("A", "B", "C")
        )), actionButton(ns("generate_graphs"), "Run")
      ), div(id = "a", card(DTOutput(
        NS(id, "table_mainpanel")
      )))))
    }
    
    mod_server <- function(id) {
      moduleServer(id, function(input, output, session) {
        elements_hidden <- reactiveVal(NULL)
        observeEvent(input$generate_graphs, {
          print("Hiding")
          shinyjs::hide(id = "a", asis = TRUE)
          shinyjs::hide(id = "b", asis = TRUE)
          elements_hidden(Sys.time())
        })
        
        observe({
          req(elements_hidden())
          if((Sys.time() - elements_hidden()) < 10L){
            invalidateLater(500L)
            print("...sleeping...")
          } else {
            shinyjs::show(id = "a", asis = TRUE)
            shinyjs::show(id = "b", asis = TRUE)
            print("Done")
          }
        })
      })
    }
    
    shinyApp(ui = page_fluid(
      useShinyjs(),
      page_navbar(
        title = "Test",
        collapsible = TRUE,
        id = "navbar",
        fillable = "Dashboard",
        nav_menu('Data section', nav_panel('Upload Data', mod_ui("upload_data")), )
      )
    ), server = function(session, input, output) {
      mod_server("upload_data")
    })
    

    Regarding your approach inside the observeEvent I'd suggest reading about shiny's reactive cycle. Please see this related question.