【问题标题】:How to use sparklines in DTedit如何在 DTedit 中使用迷你图
【发布时间】:2021-01-19 23:53:26
【问题描述】:

我有一个使用 DT 的闪亮应用程序如下(代码 sn-p):

output$table <- DT::renderDataTable({
    DT::datatable(
      data = table, 
      escape = FALSE,
      rownames = FALSE,
      selection = "single",
      options = list(...),
      fnDrawCallback = htmlwidgets::JS('function(){HTMLWidgets.staticRender();}')
    ))) %>%
    spk_add_deps()

table 中的迷你图列是使用sparklines 函数spk_chr 创建的。 这可以按预期工作,并且我在使用 JS fnDrawCallback 的预期列中有很好的迷你图。 我需要在 DT 中编辑对象,我开始使用 DT 中的编辑功能。这也有效,但从美学上来说并不那么令人愉悦(恕我直言)。

因此我想开始使用DTedit。我写了一个shiny 应用程序,除了sparklines 功能外,我可以完成这项工作。我正在使用 David Fong 的 DTedit 版本(版本 2.2.1,请参阅 here)。函数dtedit 返回一个reactiveValues 对象并且不能传递给spk_add_deps,因为后者需要一个htlmwidget。 我很难找到一种方法来完成这项工作。如何将迷你图所需的依赖项添加到 dtedit 对象? 有人可以帮忙吗?

这里是使用DTedit的应用程序的相关部分:

table_react <- reactiveVal(table)

table_dt <- dtedit(
  input, output,
  name = 'table',
  thedata = table_react,
  datatable.rownames = FALSE, # needed for the format*() functions to work
  edit.cols = edit_month,
  datatable.call = function(...) { DT::datatable(...) },
  datatable.options = list(
                      dom = "t",
                      ordering = FALSE,
                      paging = FALSE,
                      autoWidth = FALSE,
                      scrollY = "100vh",
                      scrollCollapse = FALSE,
                      fnDrawCallback = htmlwidgets::JS('function(){HTMLWidgets.staticRender();}'),
                      columnDefs = list(...),
  callback.update = KPI.update.callback
  ) 

【问题讨论】:

    标签: r shiny dt sparklines


    【解决方案1】:

    这是“基本”示例的修改版本,它或多或少是独立的。

    library(shiny)
    library(DT)
    library(magrittr)
    library(sparkline)
    library(DTedit)
    
    table <- data.frame(
      id = c('spark1', 'spark2'),
      spark = c(
        spk_chr(values = 1:3, elementId = 'spark1'),
        spk_chr(values = 3:1, elementId = 'spark2')
      )
    )
    
    shiny::shinyApp(
      ui = shiny::fluidPage(DT::DTOutput('table')),
      server = function(input, output) {
        output$table = DT::renderDataTable({
          DT::datatable(
            data = table,
            escape = FALSE,
            rownames = FALSE,
            selection = "single",
            options(fnDrawCallback = htmlwidgets::JS('function(){HTMLWidgets.staticRender();}'))
          ) %>%
            sparkline::spk_add_deps()
        })
      }
    )
    
    

    这是一个对DTedit 执行相同操作的示例,在当前develop 版本上进行了测试(稍后将变为2.2.4

    library(shiny)
    library(DT)
    library(magrittr)
    library(sparkline)
    library(DTedit)
    
    table <- data.frame(
      id = c('spark1', 'spark2'),
      spark = c(
        spk_chr(values = 1:3, elementId = 'spark1'),
        spk_chr(values = 3:1, elementId = 'spark2')
      )
    )
    
    table_react <- shiny::reactiveVal(table)
    
    server <- function(input, output) {
    
      sparkline_Results <- DTedit::dtedit(
        input, output,
        name = 'sparkline',
        thedata = table,
        datatable.rownames = FALSE,
        edit.cols = c("id"), # *not* editing the sparkline column!
        datatable.call = function(...) {
          arguments <- list(...)
          arguments$escape <- 1 # escape only the first column (not the sparkline column)
          do.call(DT::datatable, arguments) %>% # call DT::datatable with modified arguments
            sparkline::spk_add_deps()
        },
        datatable.options = list(
          fnDrawCallback = htmlwidgets::JS('function(){HTMLWidgets.staticRender();}')
        )
      )
    }
    
    ui <- shiny::fluidPage(
      shiny::h3('Sparkline example'),
      shiny::uiOutput('sparkline')
    )
    
    shiny::shinyApp(ui = ui, server = server)
    

    请注意,包含迷你图数据的列被排除编辑,因为目前没有编辑迷你图数据的方法。

    这是一个修改示例,它使用shinyalert(2.0.0 版)来允许编辑迷你图数据!请注意,此示例需要 DTedit 的当前 develop 分支(或版本 2.2.4+,当 2.2.4 发布时),因为此示例依赖于对仅可编辑一列时发生的错误的错误修复.

    library(shiny)
    library(DT)
    library(magrittr)
    library(sparkline)
    library(shinyalert) # version 2.0.0
    library(DTedit) # version 2.2.4 (when released), or current 'develop' branch
    
    table <- data.frame(
      id = c('spark1', 'spark2'),
      spark = c(
        sparkline::spk_chr(values = 1:3, elementId = 'spark1'),
        sparkline::spk_chr(values = 3:1, elementId = 'spark2')
      )
    )
    
    table_react <- shiny::reactiveVal(table)
    
    server <- function(input, output) {
    
      my.callback.actionButton <- function(data, row, buttonID) {
        # data - the current copy of 'thedata'
        # row - the row number of the clicked button
        # buttonID - the buttonID of the clicked button
    
        # in this case, only one action button per row,
        # so no need to pay attention to buttonID
    
        shinyalert::shinyalert(
          html = TRUE,
          text = shiny::tagList(
            shiny::textInput(
              "sparkvector",
              "List of numbers",
              paste(as.character(1:5), collapse = ", ")
            )
          ),
          showCancelButton = TRUE,
          callbackR = function(x) {
            if (x == TRUE) {
              # only if closed without the 'escape/cancel'
              temp <- table_react()
              temp[row, 2] <- sparkline::spk_chr(
                as.numeric(unlist(strsplit(input$sparkvector, ","))),
                elementId = temp[row, 1]
              )
              table_react(temp)
              # since table_react is a reactive,
              # dtedit will 'react' to the change in table_react
            }
          }
        )
        return(data)
      }
    
      sparkline_Results <- DTedit::dtedit(
        input, output,
        name = 'sparkline',
        thedata = table_react,
        datatable.rownames = FALSE,
        edit.cols = c("id"), # *not* editing the sparkline column!
        datatable.call = function(...) {
          arguments <- list(...)
          arguments$escape <- 1 # escape only the first column (not the sparkline column)
          do.call(DT::datatable, arguments) %>% # call DT::datatable with modified arguments
            sparkline::spk_add_deps()
        },
        datatable.options = list(
          fnDrawCallback = htmlwidgets::JS('function(){HTMLWidgets.staticRender();}')
        ),
        action.buttons = list(
          myaction = list( # the 'myaction' name is arbitrary
            columnLabel = "Spark edit",
            buttonLabel = "Edit spark",
            buttonPrefix = "sparky"
          )
        ),
        callback.actionButton = my.callback.actionButton
      )
    
      shiny::observeEvent(
        sparkline_Results$thedata, ignoreInit = TRUE, {
        # update local copy of the table when DTedit's copy is edited
          table_react(sparkline_Results$thedata)
        })
    }
    
    ui <- shiny::fluidPage(
      shinyalert::useShinyalert(),
      shiny::h3('Sparkline example'),
      shiny::uiOutput('sparkline')
    )
    
    shiny::shinyApp(ui = ui, server = server)
    
    

    【讨论】:

    • 谢谢大卫,我会试试这个并评论我的表现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-27
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    • 2017-01-06
    • 2019-06-12
    • 2017-12-30
    相关资源
    最近更新 更多