Shiny DataTable: отключить выбор строки для определенных строк

Я пытаюсь определить, возможно ли для shiny DataTable отключить выбор строк для определенных строк.

Используя параметр selection в DT::datatable, я могу предварительно выбрать строки, определить, выбирает ли пользователь строки или столбцы или и то, и другое, и полностью отключить выбор, но мне не ясно, могу ли я указать конкретные строки для исключения. Это возможно?

С Уважением


person Carl    schedule 18.02.2016    source источник


Ответы (1)


С расширением Select вы можете:

library(DT)
library(shiny)

dat <- iris[1:17,]

rowCallback <- c(
  "function(row, data, displayNum, displayIndex){",
  "  var indices = [0, 2, 4, 15];",
  "  if(indices.indexOf(displayIndex) > -1){",
  "    $(row).find('td').addClass('notselectable');",
  "  }",
  "}"
)

shinyApp(
  ui = fluidPage(
    DTOutput("table")
  ),
  server = function(input, output, session) {    
    output[["table"]] <- renderDT({
      dat %>%
        datatable(options = list(
          rowCallback = JS(rowCallback), 
          select = list(style = "multi", selector = "td:not(.notselectable)")
        ), 
        extensions = "Select", selection = "none"
        )
    }, server = FALSE)
  }
)

Но если вам нужны индексы выбранных строк в input$table_rows_selected, для этого нужно написать код на JavaScript:

callback <- 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);",
  "});"
)

shinyApp(
  ui = fluidPage(
    DTOutput("table")
  ),
  server = function(input, output, session) {    
    output[["table"]] <- renderDT({
      dat %>%
        datatable(
          callback = JS(callback),
          options = list(
            rowCallback = JS(rowCallback), 
            select = list(style = "multi", selector = "td:not(.notselectable)")
          ), 
          extensions = "Select", selection = "none"
        )
    }, server = FALSE)
    observe({
      print(input[["table_rows_selected"]])
    })
  }
)

введите здесь описание изображения

person Stéphane Laurent    schedule 11.06.2019
comment
Спасибо, что разместили это решение @ Stéphane, оно мне действительно помогло. Мне было интересно, как я могу передать R-вектор номеров строк (например, disabled = c(1,2,3)) в rowCallback? Я обхожусь с paste0(" var indices = ", toJSON(disabled), ";"), но это кажется хакерским. - person user51462; 18.06.2019
comment
@ user51462 Вы можете делать sprintf(" var indices = [%s];", paste0(disabled, collapse = ",") - person Stéphane Laurent; 18.06.2019
comment
это все еще работает с сортировкой столбцов? Предположим, вы сортируете строки в соответствии с Species в порядке убывания, тогда строки 101, 103, 105 и 116 отключаются, потому что их displayIndex теперь равны 0, 2, 4 и 15 соответственно в результате сортировки. Но что, если бы я хотел отключить строки в соответствии с их именами, чтобы 1, 3, 5 и 16 всегда были отключены независимо от их displayIndex? - person user51462; 16.08.2019
comment
Я попытался заменить displayIndex на dataIndex, поскольку документация определяет его как внутренний индекс DataTables для строки, но это не работает. Я написал об этом здесь Можно, пожалуйста, взглянуть? - person user51462; 16.08.2019
comment
Отлично, что работает. Но как это сделать для определенных столбцов? - person Indranil Gayen; 17.02.2020
comment
Я только что придумал решение для столбцов " $(row).find('td:nth-child(1)').addClass('notselectable');", - person Indranil Gayen; 17.02.2020
comment
Это работает как задумано? Каждый раз, когда я что-то щелкаю, наблюдатель получает два числа. Первый выше. Выбрав вторую строку, дайте [1] 2 [1] 1. Индекс где-то не работает? - person Jan Stanstrup; 03.04.2020
comment
@JanStanstrup Я только что попробовал, но такого поведения у меня нет. Вы дословно скопировали мой код? - person Stéphane Laurent; 04.04.2020
comment
Странный. Пробовал сейчас разные компьютеры. С R 3.5.2, shiny_1.3.2 и DT_0.8 я получаю ожидаемое поведение. На моем компьютере с R 3.6.3, shiny_1.4.0 и DT_0.13.2 я получаю это странное двойное срабатывание. - person Jan Stanstrup; 04.04.2020
comment
@JanStanstrup Возможно, это связано с изменением DT (я использую 0.10). Не могли бы вы попробовать заменить Shiny.setInputValue(id + '_rows_selected', indices) на Shiny.setInputValue(id + '_selected_rows', indices) и сделать print(input[["table_selected_rows"]]) в коде сервера. - person Stéphane Laurent; 04.04.2020
comment
Теперь это можно сделать с помощью собственной системы выбора (то есть без расширений Select и обратных вызовов): github. com / rstudio / DT / pull / 793 - person Jan Stanstrup; 07.04.2020