R Shiny - 使用列排序禁用数据表中的特定行 [英] R Shiny - Disabling specific rows in a datatable with column sorting

查看:15
本文介绍了R Shiny - 使用列排序禁用数据表中的特定行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的应用程序包含启用行选择的 iris 数据集的数据表.我想专门禁用前 3 行的选择.我可以使用

但是,当您对列上的行进行排序时,例如在 Species 上按降序排列,它禁用观察 101、102 和 103,因为它们现在是排序的结果表的前 3 行:

我猜这是因为 rowCallbackdisplayIndex 来禁用行.因此,在启动时,displayIndex 0、1 和 2 分别对应于 iris 数据集中的观察值 1、2 和 3,并且行回调会禁用它们的行选择,因为 indices.indexOf(displayIndex) >-1 是这些行的 true .但是在对 Species 进行排序后,displayIndex 0、1 和 2 分别对应于观察 101、102 和 103,因此回调会禁用它们.

为了解决这个问题,我尝试通过将 rowCallback 函数中的 displayIndex 更改为 dataIndex 来禁用基于行名的行.但是,这会做一些奇怪的事情,每次我在不同的列上过滤时都会禁用额外的行.以下是表格首先按 Sepal.LengthSepal.Length 和最后按 Petal.Length 排序后的示例:

这是重现上述内容的代码:

库(DT)图书馆(闪亮)disabled_rows = c(1,2,3)#注意:显示索引更改为数据索引rowCallback <- c(功能(行,数据,displayNum,数据索引){",sprintf(" var 索引 = [%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 index = table.rows({selected:true}).indexes();"," var index = Array(indexes.length);"," for(var i = 0; i 

我不知道为什么将 displayIndex 更改为 dataIndex 不起作用,我不知道还能尝试什么.dataIndex 参数 此处 的 DataTables 定义对我来说很模糊,因为我对 DT 插件不是很熟悉,所以我很感激任何帮助.

我也试过直接基于行名禁用如下:

rowCallback <- c(功能(行,数据,displayNum,displayIndex){"," 变量索引 = [0, 2, 4, 15]"," if(indices.indexOf(data[0]) > -1){"," $(row).find('td').addClass('notselectable');","}",}")

解决方案

奇怪的是dataIndex 不起作用.

您可以为行使用一些 id.

disabled_rows = paste0("'", paste0("row", c(1,2,3)), "'")rowCallback <- c(功能(行,数据,displayNum,displayIndex){",sprintf(" var 索引 = [%s];", toString(disabled_rows))," if(indices.indexOf($(row).attr('id')) > - 1){"," $(row).find('td').addClass('notselectable').css({'background-color': '#eee', 'color': '#bbb'});","}",}")数据 <- 虹膜dat$ID <- paste0("row", 1:nrow(iris))行名称 <- TRUEcolIndex <- as.integer(rowNames)output$table <- renderDT({数据表(日期,行名 = 行名,回调 = JS(get_selected_rows),class = '悬停行边框顺序列',选项 = 列表(rowId = JS(sprintf("function(data){return data[%d];}",ncol(dat)-1+colIndex)),rowCallback = JS(rowCallback),select = list(style = "multi", selector = "td:not(.notselectable)")),扩展=选择",选择=无")}, 服务器 = TRUE)

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:

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:

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.

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)

    })
  }
)

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.

EDIT: 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');",
  "  }",
  "}"
)

解决方案

It's strange that dataIndex does not work.

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 - 使用列排序禁用数据表中的特定行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆