Shiny / DT/ 切换并着色单元格后保存更改

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

Shiny / DT/ save changes when switching & coloring cells after change

问题

I've translated the code part for you:

  1. 基本上,我正在尝试连接这里的 **YBS** 的答案 https://stackoverflow.com/questions/67922144/shiny-app-with-editable-datatable-how-can-i-enable-the-modification-of-the-tabl 和 **Stéphane Laurent** 的答案来自这里 https://stackoverflow.com/questions/66949053/change-backgorund-color-of-cell-of-data-table-while-its-value-is-edited-in-rshin。
  2. 在这里,我已经尝试了结合这些代码:
  3. 所以我想要的是在左侧的类别之间切换时保留更改(现在可以工作),并且每个更改的单元格都突出显示颜色(现在无法工作)。
  4. ```R
  5. library(tidyverse)
  6. library(shiny)
  7. library(DT)
  8. library(shinyjs)
  9. js <- HTML(
  10. "function colorizeCell(i, j){
  11. var selector = '#dtable tr:nth-child(' + i + ') td:nth-child(' + j + ')';
  12. $(selector).css({'background-color': 'yellow'});
  13. }"
  14. )
  15. colorizeCell <- function(i, j){
  16. sprintf("colorizeCell(%d, %d)", i, j)
  17. }
  18. ui<-fluidPage( useShinyjs(),
  19. tags$head(
  20. tags$script(js)
  21. ),
  22. sidebarLayout(
  23. sidebarPanel(width = 3,
  24. inputPanel(
  25. selectInput("Species", label = "Choose species",
  26. choices = levels(as.factor(iris$Species)))
  27. )),
  28. mainPanel( tabsetPanel(
  29. tabPanel("Data Table",DTOutput("iris_datatable"),
  30. hr()))
  31. )
  32. )
  33. )
  34. server <- function(input, output, session) {
  35. my_iris <- reactiveValues(df=iris,sub=NULL, sub1=NULL)
  36. observeEvent(input$Species, {
  37. my_iris$sub <- my_iris$df %>% filter(Species==input$Species)
  38. my_iris$sub1 <- my_iris$df %>% filter(Species!=input$Species)
  39. }, ignoreNULL = FALSE)
  40. output$iris_datatable <- renderDT({
  41. n <- length(names(my_iris$sub))
  42. DT::datatable(my_iris$sub,
  43. options = list(pageLength = 10),
  44. selection='none', editable= list(target = 'cell'),
  45. rownames= FALSE)
  46. }, server = FALSE)
  47. #
  48. observeEvent(input$iris_datatable_cell_edit,{
  49. edit <- input$iris_datatable_cell_edit
  50. i <- edit$row
  51. j <- edit$col + 1
  52. v <- edit$value
  53. runjs(colorizeCell(i, j+1))
  54. my_iris$sub[i, j] <<- DT::coerceValue(v, my_iris$sub[i, j])
  55. my_iris$df <<- rbind(my_iris$sub1,my_iris$sub)
  56. })
  57. }
  58. shinyApp(ui, server)

请注意,这只是代码的翻译部分,不包括问题或其他内容。

英文:

basically, I'm trying to connect the answers of YBS here https://stackoverflow.com/questions/67922144/shiny-app-with-editable-datatable-how-can-i-enable-the-modification-of-the-tabl and Stéphane Laurent's from here https://stackoverflow.com/questions/66949053/change-backgorund-color-of-cell-of-data-table-while-its-value-is-edited-in-rshin.

Here I have tried to combine the codes:
so what I want is to keep the changes when I switch between the categories on the left (works now) and that each changed cell is highlighted in color (does not work now).

  1. library(tidyverse)
  2. library(shiny)
  3. library(DT)
  4. library(shinyjs)
  5. js <- HTML(
  6. "function colorizeCell(i, j){
  7. var selector = '#dtable tr:nth-child(' + i + ') td:nth-child(' + j + ')';
  8. $(selector).css({'background-color': 'yellow'});
  9. }"
  10. )
  11. colorizeCell <- function(i, j){
  12. sprintf("colorizeCell(%d, %d)", i, j)
  13. }
  14. ui<-fluidPage( useShinyjs(),
  15. tags$head(
  16. tags$script(js)
  17. ),
  18. sidebarLayout(
  19. sidebarPanel(width = 3,
  20. inputPanel(
  21. selectInput("Species", label = "Choose species",
  22. choices = levels(as.factor(iris$Species)))
  23. )),
  24. mainPanel( tabsetPanel(
  25. tabPanel("Data Table",DTOutput("iris_datatable"),
  26. hr()))
  27. )
  28. )
  29. )
  30. server <- function(input, output, session) {
  31. my_iris <- reactiveValues(df=iris,sub=NULL, sub1=NULL)
  32. observeEvent(input$Species, {
  33. my_iris$sub <- my_iris$df %>% filter(Species==input$Species)
  34. my_iris$sub1 <- my_iris$df %>% filter(Species!=input$Species)
  35. }, ignoreNULL = FALSE)
  36. output$iris_datatable <- renderDT({
  37. n <- length(names(my_iris$sub))
  38. DT::datatable(my_iris$sub,
  39. options = list(pageLength = 10),
  40. selection='none', editable= list(target = 'cell'),
  41. rownames= FALSE)
  42. }, server = FALSE)
  43. #
  44. observeEvent(input$iris_datatable_cell_edit,{
  45. edit <- input$iris_datatable_cell_edit
  46. i <- edit$row
  47. j <- edit$col + 1
  48. v <- edit$value
  49. runjs(colorizeCell(i, j+1))
  50. my_iris$sub[i, j] <<- DT::coerceValue(v, my_iris$sub[i, j])
  51. my_iris$df <<- rbind(my_iris$sub1,my_iris$sub)
  52. })
  53. }
  54. shinyApp(ui, server)
  55. </details>
  56. # 答案1
  57. **得分**: 1
  58. 在这段JavaScript代码中:
  59. ```r
  60. js &lt;- HTML(
  61. &quot;function colorizeCell(i, j){
  62. var selector = &#39;#dtable tr:nth-child(&#39; + i + &#39;) td:nth-child(&#39; + j + &#39;)&#39;;
  63. $(selector).css({&#39;background-color&#39;: &#39;yellow&#39;});
  64. }&quot;
  65. )

你可以看到 #dtable。这是具有id dtable的HTML元素的选择器。但是你的数据表的id不是 dtable,而是 iris_datatable。所以你需要进行替换。

英文:

In this JavaScript code:

  1. js &lt;- HTML(
  2. &quot;function colorizeCell(i, j){
  3. var selector = &#39;#dtable tr:nth-child(&#39; + i + &#39;) td:nth-child(&#39; + j + &#39;)&#39;;
  4. $(selector).css({&#39;background-color&#39;: &#39;yellow&#39;});
  5. }&quot;
  6. )

you can see #dtable. This is the selector of the HTML element with id dtable. But the id of your datatable is not dtable, it is iris_datatable. So you have to do the replacement.

答案2

得分: 1

这部分内容的中文翻译如下:

这将起作用:删除这两行代码:

  1. my_iris$sub[i, j] &lt;&lt;- DT::coerceValue(v, my_iris$sub[i, j])
  2. my_iris$df &lt;&lt;- rbind(my_iris$sub1,my_iris$sub)

并且调整 runjs

  1. library(tidyverse)
  2. library(shiny)
  3. library(DT)
  4. library(shinyjs)
  5. js &lt;- HTML(
  6. &quot;function colorizeCell(i, j){
  7. var selector = &#39;#iris_datatable tr:nth-child(&#39; + i + &#39;) td:nth-child(&#39; + j + &#39;)&#39;;
  8. $(selector).css({&#39;background-color&#39;: &#39;yellow&#39;});
  9. }&quot;
  10. )
  11. colorizeCell &lt;- function(i, j){
  12. sprintf(&quot;colorizeCell(%d, %d)&quot;, i, j)
  13. }
  14. ui&lt;-fluidPage( useShinyjs(),
  15. tags$head(
  16. tags$script(js)
  17. ),
  18. sidebarLayout(
  19. sidebarPanel(width = 3,
  20. inputPanel(
  21. selectInput(&quot;Species&quot;, label = &quot;Choose species&quot;,
  22. choices = levels(as.factor(iris$Species)))
  23. )),
  24. mainPanel( tabsetPanel(
  25. tabPanel(&quot;Data Table&quot;,DTOutput(&quot;iris_datatable&quot;),
  26. hr()))
  27. )
  28. )
  29. )
  30. server &lt;- function(input, output, session) {
  31. my_iris &lt;- reactiveValues(df=iris,sub=NULL, sub1=NULL)
  32. observeEvent(input$Species, {
  33. my_iris$sub &lt;- my_iris$df %&gt;% filter(Species==input$Species)
  34. my_iris$sub1 &lt;- my_iris$df %&gt;% filter(Species!=input$Species)
  35. }, ignoreNULL = FALSE)
  36. output$iris_datatable &lt;- renderDT({
  37. n &lt;- length(names(my_iris$sub))
  38. DT::datatable(my_iris$sub,
  39. options = list(pageLength = 10),
  40. selection=&#39;none&#39;, editable= list(target = &#39;cell&#39;),
  41. rownames= FALSE)
  42. }, server = FALSE)
  43. #
  44. observeEvent(input$iris_datatable_cell_edit,{
  45. edit &lt;- input$iris_datatable_cell_edit
  46. i &lt;- edit$row
  47. j &lt;- edit$col + 1
  48. v &lt;- edit$value
  49. runjs(colorizeCell(i, j))
  50. })
  51. }
  52. shinyApp(ui, server)

Shiny / DT/ 切换并着色单元格后保存更改

英文:

This will work: Remove these two lines:

my_iris$sub[i, j] &lt;&lt;- DT::coerceValue(v, my_iris$sub[i, j])

my_iris$df &lt;&lt;- rbind(my_iris$sub1,my_iris$sub)

and adapt runjs

  1. library(tidyverse)
  2. library(shiny)
  3. library(DT)
  4. library(shinyjs)
  5. js &lt;- HTML(
  6. &quot;function colorizeCell(i, j){
  7. var selector = &#39;#iris_datatable tr:nth-child(&#39; + i + &#39;) td:nth-child(&#39; + j + &#39;)&#39;;
  8. $(selector).css({&#39;background-color&#39;: &#39;yellow&#39;});
  9. }&quot;
  10. )
  11. colorizeCell &lt;- function(i, j){
  12. sprintf(&quot;colorizeCell(%d, %d)&quot;, i, j)
  13. }
  14. ui&lt;-fluidPage( useShinyjs(),
  15. tags$head(
  16. tags$script(js)
  17. ),
  18. sidebarLayout(
  19. sidebarPanel(width = 3,
  20. inputPanel(
  21. selectInput(&quot;Species&quot;, label = &quot;Choose species&quot;,
  22. choices = levels(as.factor(iris$Species)))
  23. )),
  24. mainPanel( tabsetPanel(
  25. tabPanel(&quot;Data Table&quot;,DTOutput(&quot;iris_datatable&quot;),
  26. hr()))
  27. )
  28. )
  29. )
  30. server &lt;- function(input, output, session) {
  31. my_iris &lt;- reactiveValues(df=iris,sub=NULL, sub1=NULL)
  32. observeEvent(input$Species, {
  33. my_iris$sub &lt;- my_iris$df %&gt;% filter(Species==input$Species)
  34. my_iris$sub1 &lt;- my_iris$df %&gt;% filter(Species!=input$Species)
  35. }, ignoreNULL = FALSE)
  36. output$iris_datatable &lt;- renderDT({
  37. n &lt;- length(names(my_iris$sub))
  38. DT::datatable(my_iris$sub,
  39. options = list(pageLength = 10),
  40. selection=&#39;none&#39;, editable= list(target = &#39;cell&#39;),
  41. rownames= FALSE)
  42. }, server = FALSE)
  43. #
  44. observeEvent(input$iris_datatable_cell_edit,{
  45. edit &lt;- input$iris_datatable_cell_edit
  46. i &lt;- edit$row
  47. j &lt;- edit$col + 1
  48. v &lt;- edit$value
  49. runjs(colorizeCell(i, j))
  50. })
  51. }
  52. shinyApp(ui, server)

Shiny / DT/ 切换并着色单元格后保存更改

答案3

得分: 1

这是使用rowCallback的一种方法。

思路是向数据添加一些0/1列,其中1表示单元格已着色。显然,我们将这些列隐藏在数据表中,但它们确实存在于表格中:rowCallback可以访问它们。然后,每次数据表重绘时触发rowCallback,它通过读取隐藏的0/1列来为单元格分配颜色。每当我们编辑单元格并为其着色时,我们会将1放入相应的隐藏0/1列中。

  1. library(tidyverse)
  2. library(shiny)
  3. library(DT)
  4. library(shinyjs)
  5. js <- HTML(
  6. "function colorizeCell(i, j){
  7. var selector = '#iris_datatable tr:nth-child(' + i + ') td:nth-child(' + j + ')';
  8. $(selector).css({'background-color': 'yellow'});
  9. }"
  10. )
  11. colorizeCell <- function(i, j){
  12. sprintf("colorizeCell(%d, %d)", i, j)
  13. }
  14. rowCallback <- '
  15. function(row, data) {
  16. for(var j = 5; j <= 9; j++) {
  17. var colorized = data[j] == 1;
  18. if(colorized) {
  19. $("td:eq(" + (j-5) + ")", row).css({"background-color": "yellow"});
  20. }
  21. }
  22. }
  23. '
  24. isColorized <- sapply(levels(iris$Species), function(species) {
  25. m <- length(iris$Species[iris$Species == species])
  26. as.data.frame(matrix(0L, nrow = m, ncol = ncol(iris)))
  27. }, simplify = FALSE)
  28. ui<-fluidPage(
  29. useShinyjs(),
  30. tags$head(
  31. tags$script(js)
  32. ),
  33. sidebarLayout(
  34. sidebarPanel(
  35. width = 3,
  36. inputPanel(
  37. selectInput("Species", label = "Choose species",
  38. choices = levels(as.factor(iris$Species))
  39. )
  40. )
  41. ),
  42. mainPanel(
  43. tabsetPanel(
  44. tabPanel(
  45. "Data Table",
  46. DTOutput("iris_datatable"),
  47. hr()
  48. )
  49. )
  50. )
  51. )
  52. )
  53. server <- function(input, output, session) {
  54. IsColorized <- reactiveVal(isColorized)
  55. dataSubset <- reactiveVal()
  56. observeEvent(input$Species, {
  57. colorized <- IsColorized()[[input$Species]]
  58. tableData <- cbind(iris %>% filter(Species == input$Species), colorized)
  59. dataSubset(tableData)
  60. })
  61. output$iris_datatable <- renderDT({
  62. datatable(
  63. dataSubset(),
  64. options = list(
  65. pageLength = 10,
  66. rowCallback = JS(rowCallback),
  67. columnDefs = list(
  68. list(targets = 5:9, visible = FALSE)
  69. )
  70. ),
  71. selection = 'none',
  72. editable = list(target = 'cell'),
  73. rownames= FALSE
  74. )
  75. }, server = FALSE)
  76. observeEvent(input$iris_datatable_cell_edit,{
  77. edit <- input$iris_datatable_cell_edit
  78. i <- edit$row
  79. j <- edit$col + 1
  80. iscolorized <- IsColorized()
  81. iscolorized[[input$Species]][i, j] <- 1L
  82. IsColorized(iscolorized)
  83. runjs(colorizeCell(i, j))
  84. })
  85. }
  86. shinyApp(ui, server)

Shiny / DT/ 切换并着色单元格后保存更改

英文:

Here is a way using a rowCallback.

The idea is to add some 0/1 columns to the data, a 1 indicates that the cell is colorized. Obviously we hide these columns in the datatable, but they are in the table: the rowCallback has access to them. Then the rowCallback, which is triggered each time the datatable is redrawn, assigns the colors to the cells by reading the hidden 0/1 columns. And each time we color a cell when we edit it, we put a 1 in the corresponding hidden 0/1 column.

  1. library(tidyverse)
  2. library(shiny)
  3. library(DT)
  4. library(shinyjs)
  5. js &lt;- HTML(
  6. &quot;function colorizeCell(i, j){
  7. var selector = &#39;#iris_datatable tr:nth-child(&#39; + i + &#39;) td:nth-child(&#39; + j + &#39;)&#39;;
  8. $(selector).css({&#39;background-color&#39;: &#39;yellow&#39;});
  9. }&quot;
  10. )
  11. colorizeCell &lt;- function(i, j){
  12. sprintf(&quot;colorizeCell(%d, %d)&quot;, i, j)
  13. }
  14. rowCallback &lt;- &#39;
  15. function(row, data) {
  16. for(var j = 5; j &lt;= 9; j++) {
  17. var colorized = data[j] == 1;
  18. if(colorized) {
  19. $(&quot;td:eq(&quot; + (j-5) + &quot;)&quot;, row).css({&quot;background-color&quot;: &quot;yellow&quot;});
  20. }
  21. }
  22. }
  23. &#39;
  24. isColorized &lt;- sapply(levels(iris$Species), function(species) {
  25. m &lt;- length(iris$Species[iris$Species == species])
  26. as.data.frame(matrix(0L, nrow = m, ncol = ncol(iris)))
  27. }, simplify = FALSE)
  28. ui&lt;-fluidPage(
  29. useShinyjs(),
  30. tags$head(
  31. tags$script(js)
  32. ),
  33. sidebarLayout(
  34. sidebarPanel(
  35. width = 3,
  36. inputPanel(
  37. selectInput(&quot;Species&quot;, label = &quot;Choose species&quot;,
  38. choices = levels(as.factor(iris$Species))
  39. )
  40. )
  41. ),
  42. mainPanel(
  43. tabsetPanel(
  44. tabPanel(
  45. &quot;Data Table&quot;,
  46. DTOutput(&quot;iris_datatable&quot;),
  47. hr()
  48. )
  49. )
  50. )
  51. )
  52. )
  53. server &lt;- function(input, output, session) {
  54. IsColorized &lt;- reactiveVal(isColorized)
  55. dataSubset &lt;- reactiveVal()
  56. observeEvent(input$Species, {
  57. colorized &lt;- IsColorized()[[input$Species]]
  58. tableData &lt;- cbind(iris %&gt;% filter(Species == input$Species), colorized)
  59. dataSubset(tableData)
  60. })
  61. output$iris_datatable &lt;- renderDT({
  62. datatable(
  63. dataSubset(),
  64. options = list(
  65. pageLength = 10,
  66. rowCallback = JS(rowCallback),
  67. columnDefs = list(
  68. list(targets = 5:9, visible = FALSE)
  69. )
  70. ),
  71. selection = &#39;none&#39;,
  72. editable = list(target = &#39;cell&#39;),
  73. rownames= FALSE
  74. )
  75. }, server = FALSE)
  76. observeEvent(input$iris_datatable_cell_edit,{
  77. edit &lt;- input$iris_datatable_cell_edit
  78. i &lt;- edit$row
  79. j &lt;- edit$col + 1
  80. iscolorized &lt;- IsColorized()
  81. iscolorized[[input$Species]][i, j] &lt;- 1L
  82. IsColorized(iscolorized)
  83. runjs(colorizeCell(i, j))
  84. })
  85. }
  86. shinyApp(ui, server)

Shiny / DT/ 切换并着色单元格后保存更改

huangapple
  • 本文由 发表于 2023年5月30日 00:13:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76358835.html
匿名

发表评论

匿名网友

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

确定