R 如果datatable列选择器也处于活动状态,如何选择行
我有一个数据表。我希望用户能够从表中选择列(用于各种函数)。我还希望用户能够选中一些框。但是,当用户选中“我的应用程序”中的复选框时,该列也会被选中。我不想发生这种事。我怎样才能阻止这一切 ui.RR 如果datatable列选择器也处于活动状态,如何选择行,r,shiny,datatables,dt,R,Shiny,Datatables,Dt,我有一个数据表。我希望用户能够从表中选择列(用于各种函数)。我还希望用户能够选中一些框。但是,当用户选中“我的应用程序”中的复选框时,该列也会被选中。我不想发生这种事。我怎样才能阻止这一切 ui.R ui<-fluidPage( # box(width=12, h3(strong("My picker"),align="center"), hr(), # column(6,offset = 6, HTML('<div class="btn-group" role=
ui<-fluidPage(
# box(width=12,
h3(strong("My picker"),align="center"),
hr(),
# column(6,offset = 6,
HTML('<div class="btn-group" role="group" aria-label="Basic example">'),
actionButton(inputId = "Del_row_head",label = "Delete selected rows"),
HTML('</div>'),
# ),
#column(12,dataTableOutput("Main_table")),
tags$script(HTML('$(document).on("click", "input", function () {
var checkboxes = document.getElementsByName("row_selected");
var checkboxesChecked = [];
for (var i=0; i<checkboxes.length; i++) {
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i].value);
}
}
Shiny.onInputChange("checked_rows",checkboxesChecked);
})')),
tags$script("$(document).on('click', '#Main_table button', function () {
Shiny.onInputChange('lastClickId',this.id);
Shiny.onInputChange('lastClick', Math.random())
});"),
dashboardPage(
dashboardHeader(title = 'My shiny'),
dashboardSidebar(),
dashboardBody( DT::dataTableOutput("endotable")))
)
RV <- reactiveValues(mtcars)
server <- function(input, output) {
output$endotable = DT::renderDT({
if (!is.null(mtcars)) {
mtcars[["Select"]]<-paste0('<input type="checkbox" name="row_selected" value="Row',1:nrow(mtcars),'"><br>')
mtcars[["Actions"]]<-
paste0('
<div class="btn-group" role="group" aria-label="Basic example">
<button type="button" class="btn btn-secondary delete" id=delete_',1:nrow(mtcars),'>Delete</button>
</div>
')
}
datatable(mtcars,escape=F,options = list(scrollX = TRUE,pageLength = 5),selection = list(target = 'column'))
},selection = list(target = 'column'),escape=F,options = list(scrollX = TRUE,pageLength = 5))
observeEvent(input$Del_row_head,{
row_to_del=as.numeric(gsub("Row","",input$checked_rows))
mtcars=mtcars[-row_to_del]}
)
observeEvent(input$lastClick,
{
if (input$lastClickId%like%"delete")
{
row_to_del=as.numeric(gsub("delete_","",input$lastClickId))
RV$data=RV$data[-row_to_del]
}
else if (input$lastClickId%like%"modify")
{
showModal(modal_modify)
}
}
)
}
shinyApp(ui = ui, server = server)
ui将选择设置为“无”
;我们将在Select
扩展名和回调的帮助下“手动”定义选择行为。启用此扩展,使用选项select=“api”
,并将类notselectable
属性设置为第12列和第13列(“选择”和“操作”):
现在返回回调:
callback <- c(
"table.on('click', 'tbody td', function(){",
" // if the column is already selected, deselect it:",
" if(table.column(this, {selected: true}).length){",
" table.column(this).deselect();",
" // otherwise, select the column unless there's the class 'notselectable':",
" } else if(!$(this).hasClass('notselectable')){",
" table.column(this).select();",
" }",
"});"
)
编辑2
要获取选定列的索引,请执行以下操作:
callback <- c(
"var ncols = table.columns().count();",
"var tbl = table.table().node();",
"var tblID = $(tbl).closest('.datatables').attr('id');",
"table.on('click', 'tbody td', function(){",
" // if the column is selected, deselect it:",
" if(table.column(this, {selected: true}).length){",
" table.column(this).deselect();",
" // otherwise, select the column unless it's among the last two columns:",
" } else if([ncols-1, ncols-2].indexOf(table.column(this).index()) === -1){",
" table.column(this).select();",
" }",
" // send selected columns to Shiny",
" var indexes = table.columns({selected:true}).indexes();",
" var indices = Array(indexes.length);",
" for(var i = 0; i < indices.length; ++i){",
" indices[i] = indexes[i];",
" }",
" Shiny.setInputValue(tblID + '_columns_selected', indices);",
"});"
)
好啊谢谢@StephaneLaurent。real app中的表格是被动的,可以添加新的列,以便targets=c(12,13)将停止显示表格。如何将最后两列定义为不可选择,而不是特定的列号?@SebastianZekilist(className=“notselective”,targets=c(-1,-2))
有效,但我不确定如果添加列,这是否正确。试试看。@SebastianZeki看到我的编辑了。也许这个解决方案更好。我刚刚意识到表现在不允许我使用从其他函数中选择的输入$endotable\u columns\u返回的值。为什么会这样?如何允许?@SebastianZeki啊,是的,我们也必须手动定义。请参阅我的第二次编辑。
callback <- c(
"var ncols = table.columns().count();",
"table.on('click', 'tbody td', function(){",
" // if the column is selected, deselect it:",
" if(table.column(this, {selected: true}).length){",
" table.column(this).deselect();",
" // otherwise, select the column unless it's among the last two columns:",
" } else if([ncols-1, ncols-2].indexOf(table.column(this).index()) === -1){",
" table.column(this).select();",
" }",
"});"
)
datatable(mtcars, escape=FALSE, callback = JS(callback),
extensions = "Select", selection = "none",
options = list(
scrollX = TRUE,
pageLength = 5,
select = "api"))
callback <- c(
"var ncols = table.columns().count();",
"var tbl = table.table().node();",
"var tblID = $(tbl).closest('.datatables').attr('id');",
"table.on('click', 'tbody td', function(){",
" // if the column is selected, deselect it:",
" if(table.column(this, {selected: true}).length){",
" table.column(this).deselect();",
" // otherwise, select the column unless it's among the last two columns:",
" } else if([ncols-1, ncols-2].indexOf(table.column(this).index()) === -1){",
" table.column(this).select();",
" }",
" // send selected columns to Shiny",
" var indexes = table.columns({selected:true}).indexes();",
" var indices = Array(indexes.length);",
" for(var i = 0; i < indices.length; ++i){",
" indices[i] = indexes[i];",
" }",
" Shiny.setInputValue(tblID + '_columns_selected', indices);",
"});"
)
callback <- c(
"var ncols = table.columns().count();",
"var tbl = table.table().node();",
"var tblID = $(tbl).closest('.datatables').attr('id');",
"table.on('click', 'tbody td', function(){",
" // if the column is selected, deselect it:",
" if(table.column(this, {selected: true}).length){",
" table.column(this).deselect();",
" // otherwise, select the column unless it's among the last two columns:",
" } else if([ncols-2, ncols-3].indexOf(table.column(this).index()) === -1){",
" table.column(this).select();",
" }",
" // send selected columns to Shiny",
" var indexes = table.columns({selected:true}).indexes();",
" var indices = Array(indexes.length);",
" for(var i = 0; i < indices.length; ++i){",
" indices[i] = indexes[i];",
" }",
" Shiny.setInputValue(tblID + '_columns_selected', indices);",
"});",
"/* ---------------------------------------------------------- */",
"// Handler to delete rows",
"Shiny.addCustomMessageHandler('deleteHandler', function(rowIDs){",
" for(var i = 0; i < rowIDs.length; ++i){",
" deleteRow(rowIDs[i]);",
" }",
"});"
)
js <- paste0(
c(
"function deleteRow(rowID){",
" var table = $('#endotable').find('table').DataTable();",
" var nrows = table.rows().count();",
" for(var i=0; i < nrows; ++i){",
" if(table.row(i).id() == rowID){",
" table.row(i).remove().draw(false);",
" break;",
" }",
" }",
"}"
),
collapse = "\n"
)
ui <- fluidPage(
tags$head(tags$script(HTML(js))),
h3(strong("My picker"),align="center"),
hr(),
HTML('<div class="btn-group" role="group" aria-label="Basic example">'),
actionButton(inputId = "Del_row_head",label = "Delete selected rows"),
HTML('</div>'),
tags$script(HTML('$(document).on("click", "input", function () {
var checkboxes = document.getElementsByName("row_selected");
var checkboxesChecked = [];
for (var i=0; i<checkboxes.length; i++) {
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i].value);
}
}
Shiny.onInputChange("checked_rows",checkboxesChecked);
})')),
# tags$script("$(document).on('click', '#Main_table button', function () {
# Shiny.onInputChange('lastClickId',this.id);
# Shiny.onInputChange('lastClick', Math.random())
# });"),
dashboardPage(
dashboardHeader(title = 'My shiny'),
dashboardSidebar(),
dashboardBody( DT::dataTableOutput("endotable")))
)
mtcars[["Select"]] <-
paste0('<input type="checkbox" name="row_selected" value="row_',1:nrow(mtcars),'"><br>')
mtcars[["Actions"]] <-
paste0('
<div class="btn-group" role="group" aria-label="Basic example">
<button type="button" class="btn btn-secondary delete" id=delete_',1:nrow(mtcars),'>Delete</button>
</div>
')
mtcars[["ROWID"]] <- paste0("row_", 1:nrow(mtcars))
server <- function(input, output, session) {
RV <- reactiveValues(data = mtcars)
# observe({
# print(input$endotable_columns_selected)
# })
output$endotable = DT::renderDT({
datatable(RV$data, escape=FALSE, callback = JS(callback),
extensions = "Select", selection = "none",
options = list(
scrollX = TRUE,
pageLength = 5,
select = "api",
rowId = JS(sprintf("function(data){return data[%d];}", ncol(RV$data))),
columnDefs = list(
list(visible = FALSE, targets = -1)
)
)
)
}, server = FALSE)
observeEvent(input[["Del_row_head"]], {
session$sendCustomMessage("deleteHandler", as.list(input$checked_rows))
})
# observeEvent(input$Del_row_head,{
# row_to_del <- as.numeric(gsub("Row","",input$checked_rows))
# RV$data <- RV$data[-row_to_del, ]
# })
#
# observeEvent(input$lastClick,
# {
# if (input$lastClickId%like%"delete")
# {
# row_to_del=as.numeric(gsub("delete_","",input$lastClickId))
# RV$data=RV$data[-row_to_del]
# }
# else if (input$lastClickId%like%"modify")
# {
# showModal(modal_modify)
# }
# }
# )
}
shinyApp(ui = ui, server = server)