1

I have a problem with costum js-functions in shiny and since I have little knowledge of js I could use a little help.

I like to have boxes with an actionLink to collapse a box and expand the other box. I found already a helpful code snippet from @DeanAttali here How to manually collapse a box in shiny dashboard, but this results in a toggle since the collapse/expand button is clicked 'programmatically'.

Below is a small example, where also the provided function by @DeanAttali is not working correct and I don't know why.

I would be very happy, if somebody could help me or give me hint.

library(shiny)
library(shinydashboard)
library(shinyjs)

jscode <- "
shinyjs.toggleBox = function(boxid) {
$('#' + boxid).closest('.box').find('[data-widget=collapse]').click();
};
shinyjs.collapseBox = function(boxid) {
$('#' + boxid).collapse('hide')};
shinyjs.expandBox = $function(boxid) {
$('#' + boxid).collapse('show')};
"

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    useShinyjs(),
    extendShinyjs(text = jscode),
    actionLink("toggleBoxes", "Toggle boxes"),
    box(id="box1", title = "box 1", width = 2,
        collapsible = TRUE,
        actionLink("openBox2", "open box 2")),
    box(id="box2", title = "box 2", width = 2,
        collapsible = TRUE, collapsed = TRUE,
        actionLink("openBox1", "open box 1"))
  )
)

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

  observeEvent(input$openBox2, {
    js$collapseBox("box1")
    js$expandBox("box2")
  })
  observeEvent(input$openBox1, {
    js$expandBox("box1")
    js$collapseBox("box2")
  })
  observeEvent(input$toggleBoxes, {
    js$toggleBox("box1")
    js$toggleBox("box2")
  })
}

shinyApp(ui = ui, server = server)
vivienneR
  • 21
  • 2
  • check out https://cran.r-project.org/web/packages/shinydashboardPlus/vignettes/improved-boxes.html – Aaron C Aug 16 '23 at 21:36

1 Answers1

0

There is a '$' before function in expandBox, which is why the whole JS code does not work. When you remove the '$', you can toggle the boxes. The JS code below allows specifically expanding/collapsing the boxes. I use the parent class to know if the box is collapsed or not (collapsed includes 'collapsed-box', expanded does not).

library(shiny)
library(shinydashboard)
library(shinyjs)

jscode <- "
shinyjs.toggleBox = function(boxid) {
$('#' + boxid).closest('.box').find('[data-widget=collapse]').click();
};
shinyjs.expandBox = function(boxid) {
if (document.getElementById(boxid).parentElement.className.includes('collapsed-box')) {
$('#' + boxid).closest('.box').find('[data-widget=collapse]').click();
}};
shinyjs.collapseBox = function(boxid) {
if (!document.getElementById(boxid).parentElement.className.includes('collapsed-box')) {
$('#' + boxid).closest('.box').find('[data-widget=collapse]').click();
}}"

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    useShinyjs(),
    extendShinyjs(text = jscode),
    actionLink("toggleBoxes", "Toggle boxes"),
    box(id="box1", title = "box 1", width = 2,
        collapsible = TRUE,
        actionLink("openBox2", "open box 2")),
    box(id="box2", title = "box 2", width = 2,
        collapsible = TRUE, collapsed = TRUE,
        actionLink("openBox1", "open box 1"))
  )
)

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

  observeEvent(input$openBox2, {
    js$collapseBox("box1")
    js$expandBox("box2")
  })
  observeEvent(input$openBox1, {
    js$expandBox("box1")
    js$collapseBox("box2")
  })
  observeEvent(input$toggleBoxes, {
    js$toggleBox("box1")
    js$toggleBox("box2")
  })
}

shinyApp(ui = ui, server = server)
Tom
  • 532
  • 3
  • 11