代码之家  ›  专栏  ›  技术社区  ›  Soren

在客户端使用afterChange事件更改rHandsontable的单元格背景

  •  4
  • Soren  · 技术社区  · 7 年前

    我想在用户在客户端编辑后更改可移动手机的背景色。通过闪亮的应用程序定义handsontable;因此,这实际上是一个关于如何在闪亮的应用程序中定义rHandsontable中的事件挂钩的问题。我试图完成的一般用例是:用户编辑单元格数据;背景颜色更改,表示已更改,正在等待保存到数据库;零钱会传回Shiny的 observeEvent() ;将更改发送到外部数据库并保存;rHandsontable将在输出上使用默认背景色重新绘制,该默认背景色将删除更改后的颜色集。结果是闪烁表示数据已保存。如果存在数据库连接错误或其他问题,则颜色将保持不变,表示数据未保存。我已经完成了一个工作示例,粘贴在下面。

    具体问题:挂钩当前使用 hot_col(1,renderer=change_hook) 然而,这并不是渲染单元,只是允许添加挂钩的一种方式。我想 hot_table() 是正确的函数,但是否可以用于注册事件?更一般地说,是否有一种更内在的方式来实现这一点?

    change_hook <- "
      function(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.hooks.add('afterChange', function(changes,source) { 
      if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') {
        row = changes[0][0];
        col = changes[0][1];
        oldval = changes[0][2];
        newval = changes[0][3];
    
        if (oldval !== newval) {
          cell = this.getCell(row,col);
          cell.style.background = 'pink';
        }
      }
    },instance);
    Handsontable.renderers.TextRenderer.apply(this, arguments);
    }"
    
    ui <- div(width=300,rHandsontableOutput(outputId="hTable"))
    server <- function(input, output, session) {
    
    df<-data.frame(col1=c("Hands","on","Table"),col2=c(100,200,300),stringsAsFactors = F)
    hTable <- reactiveVal(df)
    
    observeEvent(input$hTable, {
    withProgress(message = "Saving changes to database...", value=0.5, {
    
      Sys.sleep(1)
    
      incProgress(1, detail = "done")    
      input_hTable <- hot_to_r(input$hTable)
      hTable(input_hTable)
    })
    })
    
    output$hTable <- renderRHandsontable({
    rhandsontable(hTable(),stretchH="all",height=300) %>%
      hot_col(1,renderer=change_hook)
    })
    }
    shinyApp(ui, server)
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Tony Peng    4 年前

    下面的代码在用户编辑rhandsontable单元格后更改其背景色。

    library(shiny)
    library(rhandsontable)
    
    ui <- fluidPage(
    titlePanel ('Give it a try and make changes!'),
    mainPanel(rHandsontableOutput('table'))
    )
    
    server <- function(input, output, session) {
    
    df <- data.frame(SYMBOLS = c('AAPL', 'ALRM', 'AMZN', 'BABA', 'CRM', 'CSCO', 
                                 'FB'),
                     NAMES = c('APPLE', 'ALARM.com', 'AMAZON', 'ALIBABA', 
                               'SALESFORCE', 'CISCO', 'FACEBOOK'),
                     NOTE = c('sale', '', 'buy', '', '', '', 'watch'))
    
    output$table <- renderRHandsontable(
        rhandsontable(df))
    
    rv <- reactiveValues(row = c(), col = c())
    
    observeEvent(input$table$changes$changes, {
        
        rv$row <- c(rv$row, input$table$changes$changes[[1]][[1]])
        rv$col <- c(rv$col, input$table$changes$changes[[1]][[2]])
        
        output$table <- renderRHandsontable({
            rhandsontable(hot_to_r(input$table), row_highlight = rv$row, 
                          col_highlight = rv$col) %>% 
                hot_cols(
                    renderer = "
                     function(instance, td, row, col, prop, value, cellProperties) {
                     Handsontable.renderers.TextRenderer.apply(this, arguments);
    
                     if (instance.params) {
                     hrows = instance.params.row_highlight;
                     hrows = hrows instanceof Array ? hrows : [hrows];
                     
                     hcols = instance.params.col_highlight;
                     hcols = hcols instanceof Array ? hcols : [hcols];
                     }
    
                     for (let i = 0; i < hrows.length; i++) {
                        if (instance.params && hrows[i] == row && hcols[i] == col) {
                        td.style.background = 'pink';
                        }}
                     }"
                    )
                })
            })
    }
    
    shinyApp(ui, server)
    

    每次更改单元格时,

    1. 此单元格的行索引( input$table$changes$changes[[1]][[1]] )及其列索引( input$table$changes$changes[[1]][[2]] )附加到反应变量 rv$row rv$col 分别地
    2. 使用reactive变量再次呈现rHandsontable( rv )这包括迄今为止已更改的所有单元格的索引,最后,
    3. A. for javascript渲染器中的循环遍历 rv 一次一对,针对表中的所有列和行。如果行和列索引都匹配,则此单元格的背景色将更改为粉红色。
        2
  •  1
  •   Mahsa Chitsaz    5 年前

    搜索了一段时间后,我使用了这些页面中的信息( handsontable ,则, htmlwidgets )更改已编辑单元格的背景色。

    在afterChange功能中,将保留所有已更改单元格的列表。在afterRender函数中,这些单元格的背景颜色将更改为黄色。在afterLoadData功能中,更改单元格的背景色将重置为白色,并清空。

    library(shiny)
    library(rhandsontable)
    
    change_hook <- "function(el,x) {
    var hot = this.hot;  
    var cellChanges = [];
    
    var changefn = function(changes,source) { 
    if (source === 'edit' || source === 'undo' || source === 'autofill' || source === 'paste') {
    row = changes[0][0];
    col = changes[0][1];
    oldval = changes[0][2];
    newval = changes[0][3];
    
    if (oldval !== newval) {
      var cell = hot.getCell(row, col);
      cell.style.background = 'pink';
      cellChanges.push({'rowid':row, 'colid':col});
    }
    }
    }
    
    var renderfn = function(isForced) {
    
    for(i = 0; i < cellChanges.length; i++)
    {
    
    var rowIndex = cellChanges[i]['rowid'];
    var columnIndex = cellChanges[i]['colid'];
    
    var cell = hot.getCell(rowIndex, columnIndex);
    cell.style.background = 'yellow';
    
    }
    
    
    }
    
    var loadfn = function(initialLoad) {
    
    for(i = 0; i < cellChanges.length; i++)
        {
          var rowIndex = cellChanges[i]['rowid'];
          var columnIndex = cellChanges[i]['colid'];
    
          var cell = hot.getCell(rowIndex, columnIndex);
    
          cell.style.background = 'white';
    
        }
    cellChanges = []
    
    }
    
    
    hot.addHook('afterChange', changefn);
    hot.addHook('afterRender', renderfn);
    hot.addHook('afterLoadData', loadfn);
    
    
    }  "
    
    
    ui <- div(actionButton(inputId = "reset_button",label = "Reset")
              ,rHandsontableOutput(outputId="hTable"))
    
    
    server <- function(input, output, session) {
    
      df<-data.frame(col1=c("Hands","on","Table"),col2=c(100,200,300),stringsAsFactors = F)
      reset <- reactiveVal(0)
      hTable <- reactiveVal(df)
    
      output$hTable <- renderRHandsontable({
        r = reset()
        rht = rhandsontable(hTable(),reset=r,stretchH="all",height=300)%>%
          hot_col('col1',readOnly=T)
        reset(0)
        htmlwidgets::onRender(rht,change_hook)
      })
    
      observeEvent(input$reset_button,
                   {
                     reset(1)
                   })
    }
    
    shinyApp(ui, server)