问题描述
下面的应用程序包含启用行选择的iris
数据集的数据表.我想具体禁用对前3行的选择.我可以使用此处发布的解决方案来执行此操作.当表格在应用启动时初始化时,该解决方案可以正常工作:
The app below contains a datatable of the iris
dataset with row selection enabled. I would like to disable selection for the first 3 rows specifically. I can do this using the solution posted here. The solution works fine when the table initialises on app startup:
但是,当您对列中的行进行排序时,例如在Species
上以降序排列,它禁用了观察101、102和103,因为它们现在是排序结果,是表的前3行:
However, when you sort the rows on a column, e.g. on Species
in descending order, it disables observations 101, 102 and 103 since they are now the first 3 rows of the table as a result of the sorting:
我猜想是因为rowCallback
是displayIndex
来禁用行而发生的.因此,在启动时,displayIndex
0、1和2分别对应于虹膜数据集中的观察值1、2和3,并且行回调禁用了它们的行选择,因为这些行的indices.indexOf(displayIndex) > -1
是true
.但是在对Species
进行排序之后,displayIndex
0、1和2分别对应于观察值101、102和103,因此回调函数将其禁用.
I am guessing this happens because rowCallback
is displayIndex
to disable rows. So on startup, displayIndex
0, 1 and 2 correspond to observations 1, 2 and 3 respectively in the iris dataset and the row callback disables row selection for them since indices.indexOf(displayIndex) > -1
is true
for these rows. But after sorting on Species
, displayIndex
0, 1 and 2 correspond to observations 101, 102 and 103 respectively and so the callback disables them instead.
要解决此问题,我尝试通过将rowCallback
函数中的displayIndex
更改为dataIndex
来禁用基于行名的行.但是,这样做有些奇怪,每次我在不同的列上进行筛选时,都会禁用其他行.下面是一个示例,该表首先在Sepal.Length
上排序,然后在Sepal.Length
上排序,然后最后在Petal.Length
上排序:
To fix this, I tried disabling rows based on rowname by changing the displayIndex
in the rowCallback
function to dataIndex
. However, this does something weird where additional rows get disabled each time I filter on a different column. Here is an example after the table was first sorted on Sepal.Length
, then Sepal.Length
and then finally on Petal.Length
:
以下是复制以上代码的代码:
Here is the code to reproduce the above:
library(DT)
library(shiny)
disabled_rows = c(1,2,3)
#NOTE: displayIndex changed to dataIndex
rowCallback <- c(
"function(row, data, displayNum, dataIndex){",
sprintf(" var indices = [%s]", toString(disabled_rows - 1)),
" if(indices.indexOf(dataIndex) > -1){",
" $(row).find('td').addClass('notselectable').css({'background-color': '#eee', 'color': '#bbb'});",
" }",
"}"
)
get_selected_rows <- c(
"var id = $(table.table().node()).closest('.datatables').attr('id');",
"table.on('click', 'tbody', function(){",
" setTimeout(function(){",
" var indexes = table.rows({selected:true}).indexes();",
" var indices = Array(indexes.length);",
" for(var i = 0; i < indices.length; ++i){",
" indices[i] = indexes[i];",
" }",
" Shiny.setInputValue(id + '_rows_selected', indices);",
" }, 0);",
"});"
)
drag_selection <- c(
"var dt = table.table().node();",
"$(dt).selectable({",
" distance : 10,",
" selecting: function(evt, ui){",
" $(this).find('tbody tr').each(function(i){",
" if($(this).hasClass('ui-selecting')){",
" table.row(i).select();",
" }",
" });",
" }",
"}).on('dblclick', function(){table.rows().deselect();});"
)
shinyApp(
ui = fluidPage(
tags$head(tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js")),
DTOutput('table')
),
server = function(input, output, session) {
output$table <- renderDT({
datatable(
iris,
callback = JS(get_selected_rows),
class = 'hover row-border order-column',
options = list(
rowCallback = JS(rowCallback),
select = list(style = "multi", selector = "td:not(.notselectable)")
),
extensions = "Select", selection = 'none'
)
}, server = F)
observe({
print(input$table_rows_selected)
})
}
)
我不知道为什么将displayIndex
更改为dataIndex
不能正常工作,我也不知道还有什么尝试. dataIndex
参数此处的DataTables定义对我来说是晦涩的,因为我还不是全部熟悉DT插件,因此不胜感激.
I don't know why changing displayIndex
to dataIndex
isn't working and I don't know what else to try. The DataTables definition of the dataIndex
parameter here is obscure to me since I am not all that familiar with the DT plug-in, so I would appreciate any help.
编辑:我还尝试了直接基于行名禁用,如下所示:
I also tried disabling based on rowname directly as follows:
rowCallback <- c(
"function(row, data, displayNum, displayIndex){",
" var indices = [0, 2, 4, 15]",
" if(indices.indexOf(data[0]) > -1){",
" $(row).find('td').addClass('notselectable');",
" }",
"}"
)
推荐答案
dataIndex
无法正常工作很奇怪
It's strange that dataIndex
does not work.
您可以在行中使用一些ID.
You can use some id for the rows instead.
disabled_rows = paste0("'", paste0("row", c(1,2,3)), "'")
rowCallback <- c(
"function(row, data, displayNum, displayIndex){",
sprintf(" var indices = [%s];", toString(disabled_rows)),
" if(indices.indexOf($(row).attr('id')) > - 1){",
" $(row).find('td').addClass('notselectable').css({'background-color': '#eee', 'color': '#bbb'});",
" }",
"}"
)
dat <- iris
dat$ID <- paste0("row", 1:nrow(iris))
rowNames <- TRUE
colIndex <- as.integer(rowNames)
output$table <- renderDT({
datatable(
dat,
rownames = rowNames,
callback = JS(get_selected_rows),
class = 'hover row-border order-column',
options = list(
rowId = JS(sprintf("function(data){return data[%d];}",
ncol(dat)-1+colIndex)),
rowCallback = JS(rowCallback),
select = list(style = "multi", selector = "td:not(.notselectable)")
),
extensions = "Select", selection = 'none'
)
}, server = TRUE)
这篇关于R Shiny-通过列排序禁用数据表中的特定行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!