与此问题有点类似:How to give color to a given interval of rows of a DT table?
但是在我的情况下,我想让用户选择表中的行,然后单击按钮取消选择行,然后将先前选择的行变成提交删除的行列表的一部分,将其变灰字体(颜色:浅灰色)和斜体。这表明这些将被排除在进一步分析之外。 其次,撤消整个选择的按钮应将所有行更改回正常格式
我已经记录了选定的行并添加了取消选择功能,但是在重置行之前重新设置行的样式会使我逃脱。...
我希望实现的不确定这是否是正确的方法,但我想同时使用
values$selected_rows
和values$removed_rows
,其中第一个保留选择直到提交,然后删除(保留),如果用户决定删除另一个提交的更多行,则被删除的行可能会被选择删除。
removed_rows
也是需要设置样式的行的列表(以斜体显示为灰色)
library(shiny)
library(DT)
ui <- fluidPage(
actionButton('SubmitRemoval', 'Exclude selected rows'),
actionButton('UndoRemoval', 'Include full data'),
verbatimTextOutput('Printresult'),
DT::dataTableOutput('mytable')
)
server <- function(input, output,session) {
values <- reactiveValues()
observe({
values$selected_rows <- input$mytable_rows_selected
})
observeEvent(input$SubmitRemoval, {
values$removed_rows <- c(values$removed_rows,input$mytable_rows_selected)
dataTableProxy('mytable') %>% selectRows(NULL)
values$selected_rows <- NULL
removeTab("tabs", "mytable")
})
Remaining_mtcars <- reactive({
req( values$removed_rows)
mtcarsR <- mtcars[-c(values$removed_rows), ]
mtcarsR
})
output$Printresult <- renderText({ nrow(Remaining_mtcars()) })
observeEvent(input$UndoRemoval, {
values$removed_rows <- NULL
})
output$mytable <- DT::renderDataTable({
DT::datatable(mtcars,
extensions = c('Buttons', 'ColReorder', 'FixedHeader', 'Scroller'),
options = list(pageLength = 25,
selection = c('multiple'),
dom = 'frtipB'
)
)
})
}
runApp(list(ui = ui, server = server))
更新 @SL:我试图将您的JavaScript函数移至嵌入式按钮的DT :: JS()部分内进行提交和撤消,但无法正常工作。我想我已经接近了,但是不知道问题出在哪里。
表输出代码将遵循以下结构:
output[["mytable"]] <- renderDT({
datatable(dat,
escape = -2,
extensions = c('Buttons', 'ColReorder', 'FixedHeader', 'Scroller'),
callback = JS(callback),
options = list(
dom = 'frtipB',
initComplete = JS(initComplete),
rowId = JS(sprintf("function(data){return data[%d];}", ncol(dat))),
columnDefs = list(
list(visible = FALSE, targets = ncol(dat)),
list(className = "dt-center", targets = "_all")
),
buttons = list('copy', 'csv',
list(
extend = "collection",
text = 'Deselect',
action = DT::JS("function ( e, dt, node, config ) {
Shiny.setInputValue('SubmitRemoval', true, {priority: 'event'});
}")
## move the submit javascript here
),
list(
extend = "collection",
text = 'Restore',
action = DT::JS("function ( e, dt, node, config ) {
Shiny.setInputValue('UndoRemoval', true, {priority: 'event'});
## move the undo removal javascript here
}")
)
)
)
)
})
答案 0 :(得分:1)
这是一个更好的解决方案(花了我几个小时)。单击此按钮不会重绘表格,按列对表格进行排序也不会出错。
library(shiny)
library(DT)
initComplete <- c(
"function(settings) {",
" var table=settings.oInstance.api();",
" $('#SubmitRemoval').on('click', function(){",
" table.$('tr.selected').addClass('x');",
" });",
" $('#UndoRemoval').on('click', function(){",
" table.$('tr').removeClass('x');",
" });",
"}"
)
callback <- "
var xrows = [];
table.on('preDraw', function(e, settings) {
var tbl = settings.oInstance.api();
var nrows = tbl.rows().count();
var rows = tbl.$('tr');
var some = false; var r = 0;
while(!some && r<nrows){
if($(rows[r]).hasClass('x')){
some = true
}
r++;
}
if(some){
xrows = [];
for(var i = 0; i < nrows; i++){
if($(rows[i]).hasClass('x')){
xrows.push(rows[i].getAttribute('id'));
}
}
}
}).on('draw.dt', function(){
for(var i=0; i<xrows.length; i++){
var row = $('#' + xrows[i]);
row.addClass('x');
}
xrows = [];
});
"
ui <- fluidPage(
tags$head(
tags$style(HTML(
".x { background-color: rgb(211,211,211) !important; font-style: italic}
table.dataTable tr.selected.x td { background-color: rgb(211,211,211) !important;}"
))
),
actionButton('SubmitRemoval', 'Exclude selected rows'),
actionButton('UndoRemoval', 'Include full data'),
br(),
DTOutput('mytable')
)
server <- function(input, output,session) {
dat <- cbind(mtcars[1:6,], id=1:6)
output[["mytable"]] <- renderDT({
datatable(dat,
callback = JS(callback),
options = list(
initComplete = JS(initComplete),
rowId = JS(sprintf("function(a){return a[%d];}", ncol(dat))),
columnDefs = list(list(visible=FALSE, targets=ncol(dat)))
)
)
})
proxy <- dataTableProxy("mytable")
observeEvent(input[["UndoRemoval"]], {
proxy %>% selectRows(NULL)
})
}
shinyApp(ui, server)
以下是包含图标的版本:
library(shiny)
library(DT)
initComplete <- c(
"function(settings) {",
" var table = settings.oInstance.api();",
" var cross = '<span style=\"color:red; font-size:18px\"><i class=\"glyphicon glyphicon-remove\"></i></span>'",
" var checkmark = '<span style=\"color:red; font-size:18px\"><i class=\"glyphicon glyphicon-ok\"></i></span>'",
" $('#SubmitRemoval').on('click', function(){",
" table.$('tr.selected').addClass('x');",
" table.$('tr.selected')",
" .each(function(){$(this).find('td').eq(1).html(cross);});",
" });",
" $('#UndoRemoval').on('click', function(){",
" table.$('tr').removeClass('x');",
" table.$('tr')",
" .each(function(i){$(this).find('td').eq(1).html(checkmark);});",
" });",
"}"
)
callback <- "
var cross = '<span style=\"color:red; font-size:18px\"><i class=\"glyphicon glyphicon-remove\"></i></span>'
var xrows = [];
table.on('preDraw', function(e, settings) {
var tbl = settings.oInstance.api();
var nrows = tbl.rows().count();
var rows = tbl.$('tr');
var some = false; var r = 0;
while(!some && r<nrows){
if($(rows[r]).hasClass('x')){
some = true
}
r++;
}
if(some){
xrows = [];
for(var i = 0; i < nrows; i++){
if($(rows[i]).hasClass('x')){
xrows.push(rows[i].getAttribute('id'));
}
}
}
}).on('draw.dt', function(){
for(var i=0; i<xrows.length; i++){
var row = $('#' + xrows[i]);
row.addClass('x').find('td').eq(1).html(cross);
}
xrows = [];
});
"
ui <- fluidPage(
tags$head(
tags$style(HTML(
".x { background-color: rgb(211,211,211) !important; font-style: italic}
table.dataTable tr.selected.x td { background-color: rgb(211,211,211) !important;}"
))
),
actionButton('SubmitRemoval', 'Exclude selected rows'),
actionButton('UndoRemoval', 'Include full data'),
br(),
DTOutput('mytable')
)
server <- function(input, output,session) {
dat <- cbind(Selected = '<span style="color:red; font-size:18px"><i class="glyphicon glyphicon-ok"></i></span>',
mtcars[1:6,], id = 1:6)
output[["mytable"]] <- renderDT({
datatable(dat,
escape = -2,
callback = JS(callback),
options = list(
initComplete = JS(initComplete),
rowId = JS(sprintf("function(data){return data[%d];}", ncol(dat))),
columnDefs = list(
list(visible = FALSE, targets = ncol(dat)),
list(className = "dt-center", targets = "_all")
)
)
)
})
proxy <- dataTableProxy("mytable")
observeEvent(input[["UndoRemoval"]], {
proxy %>% selectRows(NULL)
})
}
shinyApp(ui, server)
要获取input$excludedRows
中排除的行的索引:
initComplete <- c(
"function(settings) {",
" var table = settings.oInstance.api();",
" var cross = '<span style=\"color:red; font-size:18px\"><i class=\"glyphicon glyphicon-remove\"></i></span>'",
" var checkmark = '<span style=\"color:red; font-size:18px\"><i class=\"glyphicon glyphicon-ok\"></i></span>'",
" $('#SubmitRemoval').on('click', function(){",
" table.$('tr.selected').addClass('x');",
" table.$('tr.selected')",
" .each(function(){$(this).find('td').eq(1).html(cross);});",
" var excludedRows = [];",
" table.$('tr').each(function(i, row){",
" if($(this).hasClass('x')){excludedRows.push(parseInt($(row).attr('id')));}",
" });",
" Shiny.setInputValue('excludedRows', excludedRows);",
" });",
" $('#UndoRemoval').on('click', function(){",
" table.$('tr').removeClass('x');",
" table.$('tr')",
" .each(function(i){$(this).find('td').eq(1).html(checkmark);});",
" Shiny.setInputValue('excludedRows', null);",
" });",
"}"
)
使用server = FALSE
中的renderDT
选项可以更容易:
library(shiny)
library(DT)
initComplete <- c(
"function(settings) {",
" var table = settings.oInstance.api();",
" $('#SubmitRemoval').on('click', function(){",
" table.$('tr.selected').addClass('x').each(function(){",
" var td = $(this).find('td').eq(1)[0];",
" var cell = table.cell(td);",
" cell.data('remove');",
" });",
" table.draw(false);",
" table.rows().deselect();",
" var excludedRows = [];",
" table.$('tr').each(function(i, row){",
" if($(this).hasClass('x')){excludedRows.push(parseInt($(row).attr('id')));}",
" });",
" Shiny.setInputValue('excludedRows', excludedRows);",
" });",
" $('#UndoRemoval').on('click', function(){",
" table.$('tr').removeClass('x').each(function(){",
" var td = $(this).find('td').eq(1)[0];",
" var cell = table.cell(td);",
" cell.data('ok');",
" });",
" Shiny.setInputValue('excludedRows', null);",
" });",
"}"
)
render <- c(
'function(data, type, row, meta){',
' if(type === "display"){',
' return "<span style=\\\"color:red; font-size:18px\\\"><i class=\\\"glyphicon glyphicon-" + data + "\\\"></i></span>";',
' } else {',
' return data;',
' }',
'}'
)
ui <- fluidPage(
tags$head(
tags$style(HTML(
".x { color: rgb(211,211,211); font-style: italic; }"
))
),
verbatimTextOutput("excludedRows"),
actionButton('SubmitRemoval', 'Exclude selected rows'),
actionButton('UndoRemoval', 'Include full data'),
br(),
DTOutput('mytable')
)
server <- function(input, output,session) {
dat <- cbind(Selected = "ok", mtcars[1:6,], id = 1:6)
output[["mytable"]] <- renderDT({
datatable(dat,
extensions = "Select",
options = list(
initComplete = JS(initComplete),
rowId = JS(sprintf("function(data){return data[%d];}", ncol(dat))),
columnDefs = list(
list(visible = FALSE, targets = ncol(dat)),
list(className = "dt-center", targets = "_all"),
list(
targets = 1,
render = JS(render)
)
)
)
)
}, server = FALSE)
proxy <- dataTableProxy("mytable")
observeEvent(input[["UndoRemoval"]], {
proxy %>% selectRows(NULL)
})
output$excludedRows <- renderPrint({
input[["excludedRows"]]
})
}
shinyApp(ui, server)
答案 1 :(得分:0)
这是尝试。
library(shiny)
library(DT)
rowCallback <- function(rows){
c(
"function(row, data, num, index){",
sprintf(" var rows = [%s];", paste0(rows-1, collapse = ",")),
" if(rows.indexOf(index) > -1){",
" for(var i=1; i<data.length; i++){",
" $('td:eq('+i+')', row)",
" .css({'background-color': 'rgb(211,211,211)', 'font-style': 'italic'});",
" }",
" }",
"}"
)
}
ui <- fluidPage(
actionButton('SubmitRemoval', 'Exclude selected rows'),
actionButton('UndoRemoval', 'Include full data'),
br(),
DTOutput('mytable')
)
server <- function(input, output,session) {
output[["mytable"]] <- renderDT({
input[["SubmitRemoval"]]
input[["UndoRemoval"]]
rows <- isolate(input[["mytable_rows_selected"]])
datatable(mtcars,
options = list(
rowCallback = JS(rowCallback(rows))
)
)
})
proxy <- dataTableProxy("mytable")
observeEvent(input[["UndoRemoval"]], {
proxy %>% selectRows(NULL)
})
}
shinyApp(ui, server)
答案 2 :(得分:0)
这是一个变体。用户无需单击按钮即可将选定的行标记为已删除,而是单击图标。
library(shiny)
library(DT)
callback <- c(
"table.on('click', 'td:nth-child(2)', function(){",
" var td = this;",
" var cell = table.cell(td);",
" if(cell.data() === 'ok'){",
" cell.data('remove');",
" } else {",
" cell.data('ok');",
" }",
" var $row = $(td).closest('tr');",
" $row.toggleClass('excluded');",
" var excludedRows = [];",
" table.$('tr').each(function(i, row){",
" if($(this).hasClass('excluded')){",
" excludedRows.push(parseInt($(row).attr('id')));",
" }",
" });",
" Shiny.setInputValue('excludedRows', excludedRows);",
"})"
)
restore <- c(
"function(e, table, node, config) {",
" table.$('tr').removeClass('excluded').each(function(){",
" var td = $(this).find('td').eq(1)[0];",
" var cell = table.cell(td);",
" cell.data('ok');",
" });",
" Shiny.setInputValue('excludedRows', null);",
"}"
)
render <- c(
'function(data, type, row, meta){',
' if(type === "display"){',
' return "<span style=\\\"color:red; font-size:18px\\\"><i class=\\\"glyphicon glyphicon-" + data + "\\\"></i></span>";',
' } else {',
' return data;',
' }',
'}'
)
ui <- fluidPage(
tags$head(
tags$style(HTML(
".excluded { color: rgb(211,211,211); font-style: italic; }"
))
),
fluidRow(
column(
6,
tags$label("Excluded rows"),
verbatimTextOutput("excludedRows")
),
column(
6,
tags$label("Included rows"),
verbatimTextOutput("includedRows")
)
),
br(),
DTOutput('mytable')
)
server <- function(input, output,session) {
dat <- cbind(Selected = "ok", mtcars[1:6,], id = 1:6)
output[["mytable"]] <- renderDT({
datatable(dat,
extensions = c("Select", "Buttons"),
selection = "none",
callback = JS(callback),
options = list(
rowId = JS(sprintf("function(data){return data[%d];}", ncol(dat))),
columnDefs = list(
list(visible = FALSE, targets = ncol(dat)),
list(className = "dt-center", targets = "_all"),
list(className = "notselectable", targets = 1),
list(targets = 1, render = JS(render))
),
dom = "Bt",
buttons = list("copy", "csv",
list(
extend = "collection",
text = 'Select all rows',
action = JS(restore)
)
),
select = list(style = "single", selector = "td:not(.notselectable)")
)
)
}, server = FALSE)
output$excludedRows <- renderPrint({
input[["excludedRows"]]
})
output$includedRows <- renderPrint({
setdiff(1:nrow(dat), input[["excludedRows"]])
})
}
shinyApp(ui, server)