简体   繁体   中英

Unique row DT::renderDataTable() in Shiny R trigger query

Hi Im new to shiny and data reactivity. I hope you can help, I have a query embedded within an observe function that responds to input from a unique row selection in DT::renderDataTable(). As the user selects rows the vector increments, for example row 1 is selected and then then row 8 the vector returned is [1] 1 8. The values then feed into a query via a subset routine to get the id as a text string. ie character 8 related to id "ch10". The postgres query can only take 1 value at a time however i want to get all of the selections rbind into a dataframe before plotting all together. I can do this with a for loop but this isnt very efficient and is time consuming. Also each time it iterates and updates the plot its looping through all of the vectors again and re-plotting all the selections plus the new additions. What I need to do is add the new vector rows to the dataframe and validate if the ids are already in the dataframe, reject if already there, or add if they are not there and then plot, can this be done in an observe function? Any help would be greatly appreciated. This is the main piece of code from the observe function:

       ids <- input$x3_rows_selected
       dat1 =  isolate(paste0(dat[ids, , drop = FALSE][[1]], sep = ""))

    if (dat1[1]=='')
       return(NULL)

      result = list()
    for (i in 1:length(dat1)){
      dat2           = dbGetQuery(con2, paste0("select * from    getsession('",dat1[i],"'),  sep=""))
      dat2$sessionid = dat1[i]
      result[[i]]    = dat2

    }

    big_data = do.call(rbind, result)

Here is a potential solution that put you on the right track. I simplified it slightly, using a selectizeInput for the row selection, and a simple subset statement instead of the sql query, but the idea/implementation is very similar.

Basically, you can add two reactiveVals ; one for the selected rows, and one for the table. You can then create an observeEvent to adjust those whenever the input changes. As you can see in this solution, rows are only fetched once when they are selected, and new rows are added by the observeEvent if new selections are made. This prevents us from having to got through a for loop often.

library(shiny)

mtcars$id = seq(nrow(mtcars)) # add unique id

ui <- fluidPage(
  selectizeInput('input1','Select rows:',choices=seq(nrow(mtcars)),multiple=T),
  tableOutput('result')
)

server <- function(input,output)
{
  # initiate table with right column headers
  my_table <- reactiveVal(mtcars[0,]) 
  # initiate out selection
  selection <- reactiveVal()  

  observeEvent(input$input1, ignoreNULL = F,
               {
                 # if any from input1 not yet in our selection
                 if(any(!input$input1 %in% selection()))
                 {
                   to_add = input$input1[!input$input1 %in% selection()] # which id to add?
                   selection(c(selection(),to_add)) # update the reactiveVal
                   df_to_add = mtcars[mtcars$id==to_add,] # your sql query here
                   my_table(rbind(my_table(),df_to_add)) # update the table reactiveVal
                 }
                 else
                 {
                   # if there are rows selected that the user has deselected ...
                   if(any(!selection() %in% input$input1 ))
                   {
                     selection(input$input1) # set selection to the user input
                     # remove the deselected rows from the table
                     my_table(my_table()[my_table()$id %in% input$input1,] ) 
                   }
                 }
               })

  output$result <- renderTable({my_table()})

}
shinyApp(ui,server)

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM