Search code examples
rshinyjquery-ui-sortabledtshinymodules

Passing reactive data table server to ui in modular shiny app


I want to present a data table with one column from a data frame by default and then have a user populate other columns from the dataframe using the drag and drop package sortable.

I have a working example here when running via one file shiny app.

   library(shiny)
library(sortable)
library(DT)

a <- c("13232","24343","A434535") 
b <- c("fsf","dfgds","ggdf")
c <- c("13232","24343","A434535") 
d <- c("fsf","dfgds","ggdf")

data <-  data.frame(a,b,c,d)

ui <- fluidPage(
  tags$head(
    tags$style(HTML(".bucket-list-container {min-height: 350px;}"))
  ),
  fluidRow(
    tags$b("Data Table"),
    width = 12,
    bucket_list(
      header = "Drag the items in any desired bucket",
      group_name = "bucket_list_group",
      orientation = "horizontal",
      add_rank_list(
        text = " Specific Variables",
        labels = colnames(data),
        input_id = "rank_list_1"
      ),
      
      add_rank_list(
        text = "Contents Of Data Table",
        labels = NULL,
        input_id = "rank_list_2"
      ))
  ),
  fluidRow(
    column(
      width = 12,
      tags$b("Result"),
      column(
        width = 12,
        tags$p("Table"),
        DTOutput('tbl')
      )
    )
  )
)

server <- function(input,output) {
  output$tbl = renderDT(cbind(data[1],data[,c(input$rank_list_2)]), options = list(lengthChange = FALSE)
  )
}
shinyApp(ui, server)

While this works fine. when i try to implement this in a modular format, the data table fails to update.

ui

sort_ui <- function(id) {
  ns <- NS(id)
  tagList(
    tabsetPanel(
  tabPanel("Data Table",
           fluidRow(
             tags$b("Data Table"),
             width = 12,
             bucket_list(
               header = "Drag the items in any desired bucket",
               group_name = "bucket_list_group",
               orientation = "horizontal",
               add_rank_list(
                 text = "Contents Of Data Table",
                 labels = NULL,
                 input_id = "rank_list_1"
               ))
           ),
               add_rank_list(
                 text = "Contents Of Data Table",
                 labels = NULL,
                 input_id = "rank_list_2"
               ))
           ),
           fluidRow(
             
             column(
               width = 12,
               tags$p("Table"),
               DT::dataTableOutput(ns('table'))
             )
           )
  )

Server

sort_server <- function(input, output, session,globalSession){
  ns <- session$ns
  a <- c("13232","24343","A434535") 
  b <- c("fsf","dfgds","ggdf")
  c <- c("13232","24343","A434535") 
  d <- c("fsf","dfgds","ggdf")
  
  data <-  data.frame(a,b,c,d)
  

x <- data[1]
data <- reactive(cbind(x,ihc[,c(input$rank_list_2)]))

output$table = DT::renderDataTable(data(), options = list(stateSave = TRUE)
                                   
)
proxy <- dataTableProxy('table', session = globalSession)
}

And I call the module with

callModule(sort_server,"my_sort_module",globalSession = session)

Not sure what im doing wrong here.


Solution

  • You've had a few issues with your code:

    • the brackets in the UI part weren't right
    • you need to use ns also for the ids in the bucket_list, namely group_name and input_id
    • your data aggregation in the server part was not completely correct
    • I'm not sure why you've used the global session, I'd use the default value so that everything works smoothly with the modules
    library(shiny)
    library(sortable)
    library(DT)
    
    sort_ui <- function(id) {
      ns <- NS(id)
      tagList(
        tabsetPanel(
          tabPanel("Data Table",
                   fluidRow(
                     tags$b("Data Table"),
                     width = 12,
                     bucket_list(
                       header = "Drag the items in any desired bucket",
                       group_name = ns("bucket_list_group"),
                       orientation = "horizontal",
                       add_rank_list(
                         text = "Contents Of Data Table",
                         labels = colnames(data),
                         input_id = ns("rank_list_1")
                       ),
                       add_rank_list(
                         text = "Contents Of Data Table",
                         labels = NULL,
                         input_id = ns("rank_list_2")
                       ))
                   ),
                   fluidRow(
                     
                     column(
                       width = 12,
                       tags$p("Table"),
                       DT::dataTableOutput(ns('table'))
                     )
                   )
          )
        )
      )
    }
    
    sort_server <- function(input, output, session){
      ns <- session$ns
      a <- c("13232","24343","A434535") 
      b <- c("fsf","dfgds","ggdf")
      c <- c("13232","24343","A434535") 
      d <- c("fsf","dfgds","ggdf")
      
      data <- data.frame(a,b,c,d)
      
      table_data <- reactive({
        cbind(data[1], data[,c(input$rank_list_2)])
      })
      
      output$table = DT::renderDataTable(table_data(), options = list(stateSave = TRUE)
                                         
      )
      proxy <- dataTableProxy('table')
    }
    
    ui <- fluidPage(
      tags$head(
        tags$style(HTML(".bucket-list-container {min-height: 350px;}"))
      ),
      sort_ui("my_sort_module")
      
    )
    
    server <- function(input, output, session) {
      callModule(sort_server, "my_sort_module")
    }
    
    shinyApp(ui, server)