У меня есть таблица данных, в которую я добавил несколько столбцов флажков. Я хочу иметь возможность сортировать столбцы по значениям флажков (установленных или нет). Я протестировал много разных вещей и нашел одну часть кода, которая вроде бы работает, но, к сожалению, нет. Вот решение, предложенное здесь: R/Shiny — прокручиваемая таблица данных с флажками и общим количеством.
Я заметил, что когда вы заходите в приложение и устанавливаете флажки, фильтрация не вызывает проблем. Но если вы попытаетесь обновить флажки, сортировка сохранится.
Пример проблемы с флажками:
Чтобы воспроизвести этот пример, вот код:
library(shiny)
library(DT)
ui <- fluidPage(
br(),
fluidRow(
column(
6,
DTOutput("dtable")
),
column(
6,
verbatimTextOutput("reactiveDF")
)
)
)
checkboxColumn <- function(len, col, ...) { # `col` is the column index
inputs <- character(len)
for(i in seq_len(len)) {
inputs[i] <- as.character(
checkboxInput(paste0("checkb_", col, "_", i), label = NULL, ...)
)
}
inputs
}
dat0 <- data.frame(
fruit = c("apple", "cherry", "pineapple", "pear"),
letter = c("a", "b", "c", "d")
)
dat1 <- cbind(dat0, bool1 = FALSE, bool2 = FALSE)
dat2 <- cbind(
dat0,
check1 = checkboxColumn(nrow(dat0), 3),
check2 = checkboxColumn(nrow(dat0), 4)
)
js <- function(dtid, cols, ns = identity) {
code <- vector("list", length(cols))
for(i in seq_along(cols)) {
col <- cols[i]
code[[i]] <- c(
sprintf(
"$('body').on('click', '[id^=checkb_%d_]', function() {",
col),
" var id = this.getAttribute('id');",
sprintf(
" var i = parseInt(/checkb_%d_(\\d+)/.exec(id)[1]);",
col),
" var value = $(this).prop('checked');",
sprintf(
" var info = [{row: i, col: %d, value: value}];",
col),
sprintf(
" Shiny.setInputValue('%s', info);",
ns(sprintf("%s_cell_edit:DT.cellInfo", dtid))
),
"});"
)
}
do.call(c, code)
}
checkboxesColumns <- c(3, 4)
render <- function(col) {
sprintf('
function(data, type, row, meta) {
if (type == "sort") {
var i = meta.row + 1;
var $box = $("#checkb_%d_" + i);
data = $box.prop("checked") ? "true" : "false";
}
return data;
}', col)
}
server <- function(input, output, session) {
Dat <- reactiveVal(dat1)
output[["dtable"]] <- renderDT({
datatable(
dat2,
rownames = TRUE,
escape = FALSE,
editable = list(
target = "cell", disable = list(columns = checkboxesColumns)
),
selection = "none",
callback = JS(js("dtable", checkboxesColumns)),
options = list(
columnDefs = list(
list(targets = 3, render = JS(render(3))),
list(targets = 4, render = JS(render(4)))
)
)
)
}, server = FALSE)
observeEvent(input[["dtable_cell_edit"]], {
info <- input[["dtable_cell_edit"]] # this input contains the info of the edit
Dat(editData(Dat(), info))
})
output[["reactiveDF"]] <- renderPrint({
Dat()
})
}
shinyApp(ui, server)
Есть ли какое-нибудь решение этой проблемы?
Предоставьте достаточно кода, чтобы другие могли лучше понять или воспроизвести проблему.





Идея состоит в том, что мы определяем невидимый числовой столбец для каждого столбца флажка, который содержит значения 0 или 1 в зависимости от того, установлен ли флажок в соответствующей ячейке, и что мы используем эти числовые столбцы для упорядочивания столбцов флажка с помощью orderData.
library(shiny)
library(DT)
ui <- fluidPage(
br(),
fluidRow(
column(
6,
DTOutput("dtable")
),
column(
6,
verbatimTextOutput("reactiveDF")
)
)
)
checkboxColumn <- function(len, col, ...) { # `col` is the column index
inputs <- character(len)
for(i in seq_len(len)) {
inputs[i] <- as.character(
checkboxInput(paste0("checkb_", col, "_", i), label = NULL, ...)
)
}
inputs
}
dat0 <- data.frame(
fruit = c("apple", "cherry", "pineapple", "pear"),
letter = c("a", "b", "c", "d")
)
dat2 <- cbind(
dat0,
check1 = checkboxColumn(nrow(dat0), 3),
check2 = checkboxColumn(nrow(dat0), 4),
dummy1 = 0,
dummy2 = 0
)
checkboxesColumns <- c(3, 4)
render <- function(col) {
sprintf('
function(data, type, row, meta) {
if (type == "sort") {
var i = meta.row + 1;
var $box = $("#checkb_%d_" + i);
data = $box.prop("checked") ? "true" : "false";
}
return data;
}', col)
}
server <- function(input, output, session) {
output[["dtable"]] <- renderDT({
datatable(
dat2,
rownames = TRUE,
escape = FALSE,
editable = list(
target = "cell", disable = list(columns = checkboxesColumns)
),
selection = "none",
callback = JS(
c(
"table.on('click', 'tbody td',",
" function () {",
" var rowIndex = table.row(this).index();",
" var colIndex = table.column(this).index();",
" var $box = $('#checkb_' + colIndex + '_' + (rowIndex + 1));",
" var checkBoxState = $box.prop('checked') ? 1 : 0;",
" table.cell({",
" row: rowIndex,",
" column: colIndex + 2",
" }).data(checkBoxState).draw();",
" })"
)
),
options = list(
columnDefs = list(
list(targets = 3, render = JS(render(3)), orderData = 5),
list(targets = 4, render = JS(render(4)), orderData = 6),
list(targets = 5, visible = FALSE),
list(targets = 6, visible = FALSE)
)
)
)
}, server = FALSE)
}
shinyApp(ui, server)
Работает отлично! Я просто добавил reactiveVal, потому что он мне нужен, и объединил два обратных вызова, так что у меня есть значения, и я могу их сортировать :)
Поделитесь минимальным воспроизводимым примером проблемы. Сюда входит код и соответствующие данные. Это единственный способ получить помощь здесь, на Stack Overflow.