2

I've tried in many way but I can't find a solution. I've made an app for which some calculation are made according to some other number selected through the DT Selection funcionality. On this app is possible to upload a sort of backup which restore the state of things. Some of the elements which are restored are also the selection made on several DT Tables.

The problem is here, in fact, when I restore the backup, selection are not restored until I open the DT table tab.


I've prepared a test app, in the first tab you can see the selection made in the DT table in Tab 2 and 3.

When you start the app you can notice the selection list is actually NULL.

If you switch to tab 2 and the you go back to the first tab you can notice the preselection made are then loaded. The same happen then if you open the third app.

Is there any way to have already the list loaded with preselection without actually opening manually all the tab and let the DT tab refresh the pre-selection?

Thank you all in advance!


library(shiny)

presel1 = matrix(c(1,1,
                   2,1,
                   4,4), nrow = 3, ncol = 2)

presel2 = matrix(c(1,2,
                   2,2,
                   4,2), nrow = 3, ncol = 2)

ex_matrix = matrix(c(1,2,3,4,
                     1,2,3,4,
                     1,2,3,4,
                     1,2,3,4), nrow = 4, ncol = 4 )

ui <- function(x) {
                   fluidPage(
                      mainPanel(
                          tabsetPanel(
                               tabPanel("tab1",
                                verbatimTextOutput("results")
                                 ),
                                tabPanel("tab2",
                                 DT::DTOutput("table1")
                                ),
                                tabPanel("tab3",
                                 DT::DTOutput("table2")
                                )
                              )
                         )
                  )
     }

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

    output$table1 = DT::renderDT(
      DT::datatable(
              ex_matrix,
              options = list(dom = "t", ordering = F),
              selection = list(
              target = 'cell',
              selected = presel1)
        )
      ) 
    
    output$table2 = DT::renderDT(
          DT::datatable(
          ex_matrix,
          options = list(dom = "t", ordering = F),
          selection = list(
          target = 'cell',
          selected = presel2)
      )
    )
    
    output$results = renderPrint(rbind(input$table1_cells_selected,
                                      input$table2_cells_selected))

}

shinyApp(ui, server)

I considered many options like:

outputOptions(output, "table_with_preselection", suspendWhenHidden = FALSE)

but this option does not seems to affect in any way the pre-rendering of DT tables.

Another option I considered was to create a "refresh button" to basically open all the tab automatically and let the DT table processing though it did not succeed since the following code:

  observeEvent(input$refresh_calc,{
    shinyjs::updateNavbarPage(session, "mainbar",
                                        selected = "tab1")
  },
  priority = 84)    #go to tab1

  observeEvent(input$refresh_calc,{
  shinyjs::updateNavbarPage(session, "mainbar",
  selected = "tab2")
  },
  priority = 82)    #go to tab2

  observeEvent(input$refresh_calc,{
    shinyjs::updateNavbarPage(session, "mainbar",
                                        selected = "results")
  },
  priority = 80)    #go to results

did not make load both the DT tables in tab1 and tab2 (in my app I have actually 6 tabs with selection).

I've then tried to add a delay factor to the tab switch button such this:

`  observeEvent(input$refresh_calc,{     shinyjs::delay(1000,updateNavbarPage(session, "mainbar",                                         selected = "tab1"))   },   priority = 80)    #go to results`

...
...
...

But nothing.

Do you know any way to let process the pre-selection of table without actually opneing all the tabs?

ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
  • In fact using `outputOptions(output, "table1", suspendWhenHidden = FALSE)` does make a difference. The according `renderDT` function is executed on startup (insert e.g. a `print` command for testing). However, the table inputs are populated only after the table was displayed. Use `observe({print(Sys.time()); print(names(input))})` for testing. As this is an initialization problem you could simply use a pre-defined `reactiveVal` using the known values and update it with the table inputs once they are available. – ismirsehregal Nov 25 '22 at 07:18

1 Answers1

0

Below please find an example illustrating the reactiveVal / reactiveValues workaround mentioned in my above comment:

library(DT)
library(shiny)

presel1 = matrix(c(1,1,
                   2,1,
                   4,4), nrow = 3, ncol = 2)

presel2 = matrix(c(1,2,
                   2,2,
                   4,2), nrow = 3, ncol = 2)

ex_matrix = matrix(c(1,2,3,4,
                     1,2,3,4,
                     1,2,3,4,
                     1,2,3,4), nrow = 4, ncol = 4 )

ui <- function(x) {
  fluidPage(
    mainPanel(
      tabsetPanel(
        tabPanel("tab1",
                 verbatimTextOutput("results")
        ),
        tabPanel("tab2",
                 DT::DTOutput("table1")
        ),
        tabPanel("tab3",
                 DT::DTOutput("table2")
        )
      )
    )
  )
}

server <-function(input, output, session) {
  
  output$table1 = DT::renderDT({
    print("Running renderDT for table1")
    DT::datatable(
      ex_matrix,
      options = list(dom = "t", ordering = F),
      selection = list(
        target = 'cell',
        selected = presel1)
    )
  }) 
  
  output$table2 = DT::renderDT({
    print("Running renderDT for table2")
    DT::datatable(
      ex_matrix,
      options = list(dom = "t", ordering = F),
      selection = list(
        target = 'cell',
        selected = presel2)
    )
  })
  
  observe({print(Sys.time()); print(names(input))})
  
  outputOptions(output, "table1", suspendWhenHidden = FALSE)
  outputOptions(output, "table2", suspendWhenHidden = FALSE)
  
  cells_selected <- reactiveValues(table1 = presel1, table2 = presel2)
  
  observe({
    cells_selected$table1 <- req(input$table1_cells_selected)
  })
  
  observe({
    cells_selected$table2 <- req(input$table2_cells_selected)
  })
  
  output$results = renderPrint({
    rbind(cells_selected$table1, cells_selected$table2)
  })
  
}

shinyApp(ui, server)
ismirsehregal
  • 30,045
  • 5
  • 31
  • 78