闪亮的数据表模式可编辑 - 限制特定列和行

问题描述 投票:0回答:2

我想限制数据表中列和行的可编辑模式。 目前,在这个最小的示例中,我只能编辑特定列,但它不适用于限制行(不允许行 1 到 5)。

有人有想法吗?

谢谢您的提前

library(shiny)
library(DT)
shinyApp(
  ui = fluidPage(DTOutput('tbl')),
  server = function(input, output) {
    output$tbl = renderDT(
      datatable(data = iris, 
                options = list(lengthChange = FALSE),
                editable = list(target = 'column', disable = list(columns = c(1:3), rows = c(1:5))))
    )
  }
)
r shiny dt
2个回答
0
投票

您可以从我提供的链接中调整代码,如下所示。

library(shiny)
library(DT)

disabled_rows = paste0("'", paste0("row", c(1,2,3)), "'")   ### disabled rows are listed here

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

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();});"
)
dat <- iris
dat$ID <- paste0("row", 1:nrow(iris))
rowNames <- TRUE
colIndex <- as.integer(rowNames)

shinyApp(
  ui = fluidPage(DTOutput('tbl')),
  server = function(input, output, session) {
    
    
    ### disable selected rows only
    # output$tbl <- 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)

    ###  disable selected rows and columns
    output$tbl <- renderDT({

      datatable(
        dat,
        rownames = rowNames,
        callback = JS(get_selected_rows),
        class = 'hover row-border order-column',
        options = list(
          lengthChange = FALSE,
          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", 
        editable = list(target = 'column', disable = list(columns = c(2:3) )), selection = 'none',
      )
    }, server = TRUE)

    ### disable selected columns only
    # output$tbl = renderDT(
    #   datatable(data = iris,
    #             options = list(lengthChange = FALSE),
    #             #extensions = "Select", selection = 'none',
    #             editable = list(target = 'column', disable = list( columns = c(2:3) )) )
    # )
  }
)

0
投票

解决方法:

通过忽略代理中的更改来避免修改

library(shiny)
library(DT)

forbidden_rows <- 1

disabled_rows <- paste0("'", paste0("row", forbidden_rows), "'") ### disabled rows are listed here

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('non-modifiable').css({'background-color': '#eee', 'color': '#bbb'});",
  "  }",
  "}"
)

rownames_bool <- T

colIndexfix <- as.integer(rownames_bool)

shinyApp(
  ui = fluidPage(
    DTOutput("x1")
  ),
  server = function(input, output, session) {
    x <- iris
    x$ID <- paste0("row", 1:nrow(iris))
    y <- reactiveVal(x)

    output$x1 <- renderDT({
      datatable(x,
        selection = "none",
        editable = list(
          target = "column",
          disable = list(
            columns = 0:1,
            # non functional!, just, desired https://github.com/rstudio/DT/issues/1118
            rows = 1
          )
        ),
        options(list(
          rowId = JS(sprintf(
            "function(data){return data[%d];}",
            ncol(dat) - 1 + colIndexfix
          )),
          rowCallback = JS(rowCallback)
        )),
        rownames = rownames_bool
      )
    })

    proxy <- dataTableProxy("x1")

    observeEvent(input$x1_cell_edit, {
      info <- input$x1_cell_edit

      if (rownames_bool) {
        len <- length(info$row)
        i <- info$row[2:len]
        j <- info$col[2:len]
        v <- info$value[2:len]
      }

      x <- y()

      for (k in seq_along(i)) {
        if (i[k] %in% forbidden_rows) {
          next
        }
        current_class <- class(x[[j[k]]])[1]
        coerced_value <- switch(current_class,
          numeric = as.numeric(v[k]),
          integer = as.integer(v[k]),
          character = as.character(v[k]),
          logical = as.logical(v[k]),
          factor = factor(v[k], levels = levels(x[[j[k]]])),
          v[k]
        )
        x[i[k], j[k]] <- coerced_value
      }

      y(x)
      replaceData(proxy, x, resetPaging = FALSE, rownames = rownames_bool) # important
    })
  }
)
© www.soinside.com 2019 - 2024. All rights reserved.