R/Shiny中直接从R传递参数的JavaScript方法

huangapple go评论92阅读模式
英文:

R/Shiny Javascript passing arguments directly from R

问题

我有一个使用rhandsontable的Shiny App,我希望在修改值后更改单元格的颜色。
基本上,我需要对Kat在这里提供的解决方案进行一些修改:https://stackoverflow.com/questions/73337727/in-shiny-rhandsontable-afterchange-change-multiple-cell-backgrounds-at-once/73347195#73347195。

我想要的是,根据发生更改的行的不同,有不同的颜色。我在下面实现了一个示例,在前5行中颜色是蓝色,在其余行中是粉色。但我需要帮助的地方是,如何通过R动态地将参数传递给javascript中的数组?
(因为我每次都需要不同的行,并且我希望从R中获取所需的行索引,例如通过which,然后在R中有一个向量,应该自动传递给下面的javascript函数,而不是现在的if (elem['rowind'] in [0,1,2,4])

library(shiny)
library(rhandsontable)

change_hook <- "function(el,x) {
  hot = this.hot;
  cellchngs = [];
  afterChange = function(changes, source) {
    $.each(changes, function (index, elem) {
      change = elem;                  /* gather the row, col, old, new values */
      if(change[2] !== change[3]) {   /* if old isn't the same as new */
        cellchg = ({rowind: change[0], colind: change[1]});
        cellchngs.push(cellchg);      /* add row and column indicies to array */
      }
    });
    $.each(cellchngs, function(ind, elem) { 
      td = hot.getCell(elem['rowind'], elem['colind']); /* get the html element */
if (elem['rowind'] in [0,1,2,4]){
      td.style.background = 'cyan';                     /* set background color */
}
else {
  td.style.background = 'pink';                     /* set background color */
}
    });
  }
  hot.addHook('afterChange', afterChange);  /* add event to table */
}"


ui <- div(actionButton(inputId = "reset_button",label = "Reset")
          ,rHandsontableOutput(outputId="mtcars"))


server <- function(input, output, session) {
  
  
  reset <- reactiveVal(0)
  output$mtcars <- renderRHandsontable({
    r = reset()
    rht = rhandsontable(mtcars,reset=r,stretchH="all",height=300)
    reset(0)
    htmlwidgets::onRender(rht,change_hook)
  })
  
  observeEvent(input$reset_button,
               {
                 reset(1)
               })
}

shinyApp(ui, server)
英文:

I have a Shiny App with rhandsontable where I want the cell colors to be changed after a value is modified
Basically I needed some modification of Kat's solution implemented here https://stackoverflow.com/questions/73337727/in-shiny-rhandsontable-afterchange-change-multiple-cell-backgrounds-at-once/73347195#73347195.

what I want, are different colors based on the row where the change has occurred. I have implemented an example below where in the first 5 rows the color is blue and pink in the rest, but where I would need help, how can I pass a paramter for the array in javascript dynamically via R?
(Because I need different rows everytime and I would like to get the desired row indices from R for example via ?which, then have a vector in R which should ideally automatically be passed to the javascript function below instead of the if (elem[&#39;rowind&#39;] in [0,1,2,4]) as it is now)

library(shiny)
library(rhandsontable)

change_hook &lt;- &quot;function(el,x) {
  hot = this.hot;
  cellchngs = [];
  afterChange = function(changes, source) {
    $.each(changes, function (index, elem) {
      change = elem;                  /* gather the row, col, old, new values */
      if(change[2] !== change[3]) {   /* if old isn&#39;t the same as new */
        cellchg = ({rowind: change[0], colind: change[1]});
        cellchngs.push(cellchg);      /* add row and column indicies to array */
      }
    });
    $.each(cellchngs, function(ind, elem) { 
      td = hot.getCell(elem[&#39;rowind&#39;], elem[&#39;colind&#39;]); /* get the html element */
if (elem[&#39;rowind&#39;] in [0,1,2,4]){
      td.style.background = &#39;cyan&#39;;                     /* set background color */
}
else {
  td.style.background = &#39;pink&#39;;                     /* set background color */
}
    });
  }
  hot.addHook(&#39;afterChange&#39;, afterChange);  /* add event to table */
}&quot;


ui &lt;- div(actionButton(inputId = &quot;reset_button&quot;,label = &quot;Reset&quot;)
          ,rHandsontableOutput(outputId=&quot;mtcars&quot;))


server &lt;- function(input, output, session) {
  
  
  reset &lt;- reactiveVal(0)
  output$mtcars &lt;- renderRHandsontable({
    r = reset()
    rht = rhandsontable(mtcars,reset=r,stretchH=&quot;all&quot;,height=300)
    reset(0)
    htmlwidgets::onRender(rht,change_hook)
  })
  
  observeEvent(input$reset_button,
               {
                 reset(1)
               })
}

shinyApp(ui, server)

答案1

得分: 2

我会使用onRenderdata参数(参见?htmlwidgets::onRender)。它允许在JavaScript函数中使用第三个参数:即data参数,它是一个转换为JavaScript的R对象。

change_hook <- "function(el, x, v) {
  hot = this.hot;
  cellchngs = [];
  afterChange = function(changes, source) {
    $.each(changes, function (index, elem) {
      change = elem;                  /* 收集行、列、旧值、新值 */
      if(change[2] !== change[3]) {   /* 如果旧值与新值不同 */
        cellchg = ({rowind: change[0], colind: change[1]});
        cellchngs.push(cellchg);      /* 将行和列索引添加到数组中 */
      }
    });
    $.each(cellchngs, function(ind, elem) { 
      td = hot.getCell(elem['rowind'], elem['colind']); /* 获取HTML元素 */
      if(v.indexOf(elem['rowind']) > -1) {
        td.style.background = 'cyan';                     /* 设置背景颜色 */
      } else {
        td.style.background = 'pink';                     /* 设置背景颜色 */
      }
    });
  }
  hot.addHook('afterChange', afterChange);  /* 将事件添加到表格中 */
}"

然后执行:

htmlwidgets::onRender(rht, change_hook, c(0, 1, 2, 4))
英文:

I would use the data argument of onRender (see ?htmlwidgets::onRender). It allows to use a third argument in the JavaScript function: namely this data argument, a R object, converted to JavaScript.

change_hook &lt;- &quot;function(el, x, v) {
  hot = this.hot;
  cellchngs = [];
  afterChange = function(changes, source) {
    $.each(changes, function (index, elem) {
      change = elem;                  /* gather the row, col, old, new values */
      if(change[2] !== change[3]) {   /* if old isn&#39;t the same as new */
        cellchg = ({rowind: change[0], colind: change[1]});
        cellchngs.push(cellchg);      /* add row and column indicies to array */
      }
    });
    $.each(cellchngs, function(ind, elem) { 
      td = hot.getCell(elem[&#39;rowind&#39;], elem[&#39;colind&#39;]); /* get the html element */
      if(v.indexOf(elem[&#39;rowind&#39;]) &gt; -1) {
        td.style.background = &#39;cyan&#39;;                     /* set background color */
      } else {
        td.style.background = &#39;pink&#39;;                     /* set background color */
      }
    });
  }
  hot.addHook(&#39;afterChange&#39;, afterChange);  /* add event to table */
}&quot;

and then:

htmlwidgets::onRender(rht, change_hook, c(0, 1, 2, 4))

huangapple
  • 本文由 发表于 2023年7月31日 18:30:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76802740.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定