r - Shiny: keep boxes checked on datatable after changing inputs -
i want implement checkboxes shiny app; however, i'm facing 2 problems:
- after reorder columns, checks on datatable disappear (e.g., try order table
mpg
) - after remove column, checks on datatable disappear (e.g., unchecking boxes
columns show:
)
here's dummy example (it's modified version of code this answer):
library(shiny) table = mtcars table$id = 1:nrow(mtcars) app <- list() app$ui <- pagewithsidebar( headerpanel(null), sidebarpanel( checkboxgroupinput("show_vars", "columns show:", names(table), selected = names(table)) ), mainpanel( datatableoutput("resulttable") ) ) app$server <- function(input, output, session) { output$resulttable = renderdatatable({ addcheckboxbuttons <- paste0('<input type="checkbox" name="row', table$id, '" value="', table$id, '">',"") cbind(pick = addcheckboxbuttons, table[, input$show_vars, drop = false]) }, escape = false) } runapp(app)
app
works, full implementation need solve problems 1 , 2.
based on answer provided in question:
library(shiny) mymtcars = mtcars mymtcars$id = 1:nrow(mtcars) runapp( list(ui = pagewithsidebar( headerpanel('examples of datatables'), sidebarpanel( checkboxgroupinput('show_vars', 'columns show:', names(mymtcars), selected = names(mymtcars)) ), mainpanel( datatableoutput("mytable") ) ) , server = function(input, output, session) { strd<-reactivevalues(tr=0, slrows=character(length=nrow(mymtcars))) #preserve selected rows in reactive element rowselect <- reactive({ input$rows }) # use reactive value that's equal 'checked' parameter html code observe({ strd$slrows<-ifelse(mymtcars$id %in% as.numeric(rowselect()),'checked','' ) }) #use observer column checkboxinput detect first run observeevent(input$show_vars, { strd$tr<-strd$tr+1 print(strd$tr) }, ignorenull = true) output$mytable = renderdatatable({ #if first run - nothing checked if (strd$tr==1){ addcheckboxbuttons <- paste0('<input type="checkbox" name="row', mymtcars$id, '" value="', mymtcars$id, '" >',"") } else{ # add 'checked' parameter html depending if id present in selected rows reactive value addcheckboxbuttons <- paste0('<input type="checkbox" name="row', mymtcars$id, '" value="', mymtcars$id,'" ', strd$slrows,'>',"") } #display table checkbox buttons (cbind(pick=addcheckboxbuttons, mymtcars[, input$show_vars, drop=false])) }, options = list(orderclasses = true, lengthmenu = c(5, 25, 50), pagelength = 25), escape=false, callback = "function(table) { table.on('change.dt', 'tr td input:checkbox', function() { settimeout(function () { shiny.oninputchange('rows', $(this).add('tr td input:checkbox:checked').parent().siblings(':last-child').map(function() { return $(this).text(); }).get()) }, 10); }); }") } ) )
similar, dt approach: (a bit more efficient don't create input each row , consequence won't recreate table each reactive values trigger (that's columns , rows ticks). recreates table in column reactive value trigger. can use colvis
in buttons extension in order along pure dt solution
library(shiny) library(dt) mymtcars<-mtcars shinyapp( ui = pagewithsidebar( headerpanel('examples of datatables'), sidebarpanel( checkboxgroupinput('show_vars', 'columns show:', names(mymtcars), selected = names(mymtcars)) ), mainpanel( verbatimtextoutput("selrows"), dt::datatableoutput("mytable") ) ), server = function(input, output) { strd<-reactivevalues(tr=0, slrows=c(0,0)) observe({ if(strd$tr==1){ strd$slrows<-0 } else strd$slrows<-input$mytable_rows_selected }) rowselect <- reactive({ input$mytable_rows_selected }) observeevent(input$show_vars, { strd$tr<-strd$tr+1 print(strd$tr) }, ignorenull = true) output$mytable = dt::renderdatatable({ datatable(mymtcars[, input$show_vars, drop=f], rownames=false,options = list(pagelength = 10), selection = list(mode='multiple', target='row', selected = strd$slrows) ) } ) output$selrows<-renderprint({ input$mytable_rows_selected }) } )
Comments
Post a Comment