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

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

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

问题

I've translated the code part for you:

基本上,我正在尝试连接这里的 **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。

在这里,我已经尝试了结合这些代码:
所以我想要的是在左侧的类别之间切换时保留更改(现在可以工作),并且每个更改的单元格都突出显示颜色(现在无法工作)。

```R
library(tidyverse)
library(shiny)
library(DT)
library(shinyjs)

js <- HTML(
  "function colorizeCell(i, j){
    var selector = '#dtable tr:nth-child(' + i + ') td:nth-child(' + j + ')';
    $(selector).css({'background-color': 'yellow'});
  }"
)

colorizeCell <- function(i, j){
  sprintf("colorizeCell(%d, %d)", i, j)
}

ui<-fluidPage(  useShinyjs(),
                tags$head(
                  tags$script(js)
                ),
  
                 sidebarLayout(
                   sidebarPanel(width = 3,
                                inputPanel(
                                  selectInput("Species", label = "Choose species",
                                              choices = levels(as.factor(iris$Species)))
                                )),

                   mainPanel( tabsetPanel(
                     tabPanel("Data Table",DTOutput("iris_datatable"),
                             hr()))
                 )
               )

)


server <- function(input, output, session) {
  my_iris <- reactiveValues(df=iris,sub=NULL, sub1=NULL)

  observeEvent(input$Species, {
    my_iris$sub <- my_iris$df %>% filter(Species==input$Species)
    my_iris$sub1 <- my_iris$df %>% filter(Species!=input$Species)
  }, ignoreNULL = FALSE)
  
  output$iris_datatable <- renderDT({
    n <- length(names(my_iris$sub))
    DT::datatable(my_iris$sub,
                  options = list(pageLength = 10),
                  selection='none', editable= list(target = 'cell'), 
                  rownames= FALSE)
  }, server = FALSE)
  # 
  observeEvent(input$iris_datatable_cell_edit,{
    edit <- input$iris_datatable_cell_edit
    i <- edit$row
    j <- edit$col + 1
    v <- edit$value
    runjs(colorizeCell(i, j+1))
    my_iris$sub[i, j] <<- DT::coerceValue(v, my_iris$sub[i, j])

    my_iris$df <<- rbind(my_iris$sub1,my_iris$sub)
  })
  

  
}
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).

library(tidyverse)
library(shiny)
library(DT)
library(shinyjs)
js <- HTML(
"function colorizeCell(i, j){
var selector = '#dtable tr:nth-child(' + i + ') td:nth-child(' + j + ')';
$(selector).css({'background-color': 'yellow'});
}"
)
colorizeCell <- function(i, j){
sprintf("colorizeCell(%d, %d)", i, j)
}
ui<-fluidPage(  useShinyjs(),
tags$head(
tags$script(js)
),
sidebarLayout(
sidebarPanel(width = 3,
inputPanel(
selectInput("Species", label = "Choose species",
choices = levels(as.factor(iris$Species)))
)),
mainPanel( tabsetPanel(
tabPanel("Data Table",DTOutput("iris_datatable"),
hr()))
)
)
)
server <- function(input, output, session) {
my_iris <- reactiveValues(df=iris,sub=NULL, sub1=NULL)
observeEvent(input$Species, {
my_iris$sub <- my_iris$df %>% filter(Species==input$Species)
my_iris$sub1 <- my_iris$df %>% filter(Species!=input$Species)
}, ignoreNULL = FALSE)
output$iris_datatable <- renderDT({
n <- length(names(my_iris$sub))
DT::datatable(my_iris$sub,
options = list(pageLength = 10),
selection='none', editable= list(target = 'cell'), 
rownames= FALSE)
}, server = FALSE)
# 
observeEvent(input$iris_datatable_cell_edit,{
edit <- input$iris_datatable_cell_edit
i <- edit$row
j <- edit$col + 1
v <- edit$value
runjs(colorizeCell(i, j+1))
my_iris$sub[i, j] <<- DT::coerceValue(v, my_iris$sub[i, j])
my_iris$df <<- rbind(my_iris$sub1,my_iris$sub)
})
}
shinyApp(ui, server)
</details>
# 答案1
**得分**: 1
在这段JavaScript代码中:
```r
js &lt;- HTML(
&quot;function colorizeCell(i, j){
var selector = &#39;#dtable tr:nth-child(&#39; + i + &#39;) td:nth-child(&#39; + j + &#39;)&#39;;
$(selector).css({&#39;background-color&#39;: &#39;yellow&#39;});
}&quot;
)

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

英文:

In this JavaScript code:

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

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

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

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

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)

并且调整 runjs

library(tidyverse)
library(shiny)
library(DT)
library(shinyjs)

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

colorizeCell &lt;- function(i, j){
  sprintf(&quot;colorizeCell(%d, %d)&quot;, i, j)
}

ui&lt;-fluidPage(  useShinyjs(),
                tags$head(
                  tags$script(js)
                ),
                
                sidebarLayout(
                  sidebarPanel(width = 3,
                               inputPanel(
                                 selectInput(&quot;Species&quot;, label = &quot;Choose species&quot;,
                                             choices = levels(as.factor(iris$Species)))
                               )),
                  
                  mainPanel( tabsetPanel(
                    tabPanel(&quot;Data Table&quot;,DTOutput(&quot;iris_datatable&quot;),
                             hr()))
                  )
                )
                
)


server &lt;- function(input, output, session) {
  my_iris &lt;- reactiveValues(df=iris,sub=NULL, sub1=NULL)
  
  observeEvent(input$Species, {
    my_iris$sub &lt;- my_iris$df %&gt;% filter(Species==input$Species)
    my_iris$sub1 &lt;- my_iris$df %&gt;% filter(Species!=input$Species)
  }, ignoreNULL = FALSE)
  
  output$iris_datatable &lt;- renderDT({
    n &lt;- length(names(my_iris$sub))
    DT::datatable(my_iris$sub,
                  options = list(pageLength = 10),
                  selection=&#39;none&#39;, editable= list(target = &#39;cell&#39;), 
                  rownames= FALSE)
  }, server = FALSE)
  # 
  observeEvent(input$iris_datatable_cell_edit,{
    edit &lt;- input$iris_datatable_cell_edit
    i &lt;- edit$row
    j &lt;- edit$col + 1
    v &lt;- edit$value
    runjs(colorizeCell(i, j))
  })
}
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

library(tidyverse)
library(shiny)
library(DT)
library(shinyjs)
js &lt;- HTML(
&quot;function colorizeCell(i, j){
var selector = &#39;#iris_datatable tr:nth-child(&#39; + i + &#39;) td:nth-child(&#39; + j + &#39;)&#39;;
$(selector).css({&#39;background-color&#39;: &#39;yellow&#39;});
}&quot;
)
colorizeCell &lt;- function(i, j){
sprintf(&quot;colorizeCell(%d, %d)&quot;, i, j)
}
ui&lt;-fluidPage(  useShinyjs(),
tags$head(
tags$script(js)
),
sidebarLayout(
sidebarPanel(width = 3,
inputPanel(
selectInput(&quot;Species&quot;, label = &quot;Choose species&quot;,
choices = levels(as.factor(iris$Species)))
)),
mainPanel( tabsetPanel(
tabPanel(&quot;Data Table&quot;,DTOutput(&quot;iris_datatable&quot;),
hr()))
)
)
)
server &lt;- function(input, output, session) {
my_iris &lt;- reactiveValues(df=iris,sub=NULL, sub1=NULL)
observeEvent(input$Species, {
my_iris$sub &lt;- my_iris$df %&gt;% filter(Species==input$Species)
my_iris$sub1 &lt;- my_iris$df %&gt;% filter(Species!=input$Species)
}, ignoreNULL = FALSE)
output$iris_datatable &lt;- renderDT({
n &lt;- length(names(my_iris$sub))
DT::datatable(my_iris$sub,
options = list(pageLength = 10),
selection=&#39;none&#39;, editable= list(target = &#39;cell&#39;), 
rownames= FALSE)
}, server = FALSE)
# 
observeEvent(input$iris_datatable_cell_edit,{
edit &lt;- input$iris_datatable_cell_edit
i &lt;- edit$row
j &lt;- edit$col + 1
v &lt;- edit$value
runjs(colorizeCell(i, j))
})
}
shinyApp(ui, server)

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

答案3

得分: 1

这是使用rowCallback的一种方法。

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

library(tidyverse)
library(shiny)
library(DT)
library(shinyjs)

js <- HTML(
  "function colorizeCell(i, j){
    var selector = '#iris_datatable tr:nth-child(' + i + ') td:nth-child(' + j + ')';
    $(selector).css({'background-color': 'yellow'});
  }"
)

colorizeCell <- function(i, j){
  sprintf("colorizeCell(%d, %d)", i, j)
}

rowCallback <- '
function(row, data) {
  for(var j = 5; j <= 9; j++) {
    var colorized = data[j] == 1;
    if(colorized) {
      $("td:eq(" + (j-5) + ")", row).css({"background-color": "yellow"});
    }
  }
}
'

isColorized <- sapply(levels(iris$Species), function(species) {
  m <- length(iris$Species[iris$Species == species])
  as.data.frame(matrix(0L, nrow = m, ncol = ncol(iris)))
}, simplify = FALSE)

ui<-fluidPage(
  useShinyjs(),
  tags$head(
    tags$script(js)
  ),
  
  sidebarLayout(
    sidebarPanel(
      width = 3,
      inputPanel(
        selectInput("Species", label = "Choose species",
                    choices = levels(as.factor(iris$Species))
        )
      )
    ),
    
    mainPanel( 
      tabsetPanel(
        tabPanel(
          "Data Table",
          DTOutput("iris_datatable"),
          hr()
        )
      )
    )
  )
  
)

server <- function(input, output, session) {
  
  IsColorized <- reactiveVal(isColorized)
  
  dataSubset <- reactiveVal()
  
  observeEvent(input$Species, {
    colorized <- IsColorized()[[input$Species]]
    tableData <- cbind(iris %>% filter(Species == input$Species), colorized)
    dataSubset(tableData)
  })
  
  output$iris_datatable <- renderDT({
    datatable(
      dataSubset(),
      options = list(
        pageLength = 10,
        rowCallback = JS(rowCallback),
        columnDefs = list(
          list(targets = 5:9, visible = FALSE)
        )
      ),
      selection = 'none', 
      editable = list(target = 'cell'), 
      rownames= FALSE
    )
  }, server = FALSE)
  
  observeEvent(input$iris_datatable_cell_edit,{
    edit <- input$iris_datatable_cell_edit
    i <- edit$row
    j <- edit$col + 1
    iscolorized <- IsColorized()
    iscolorized[[input$Species]][i, j] <- 1L
    IsColorized(iscolorized)
    runjs(colorizeCell(i, j))
  })
}

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.

library(tidyverse)
library(shiny)
library(DT)
library(shinyjs)

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

colorizeCell &lt;- function(i, j){
  sprintf(&quot;colorizeCell(%d, %d)&quot;, i, j)
}

rowCallback &lt;- &#39;
function(row, data) {
  for(var j = 5; j &lt;= 9; j++) {
    var colorized = data[j] == 1;
    if(colorized) {
      $(&quot;td:eq(&quot; + (j-5) + &quot;)&quot;, row).css({&quot;background-color&quot;: &quot;yellow&quot;});
    }
  }
}
&#39;

isColorized &lt;- sapply(levels(iris$Species), function(species) {
  m &lt;- length(iris$Species[iris$Species == species])
  as.data.frame(matrix(0L, nrow = m, ncol = ncol(iris)))
}, simplify = FALSE)

ui&lt;-fluidPage(
  useShinyjs(),
  tags$head(
    tags$script(js)
  ),
  
  sidebarLayout(
    sidebarPanel(
      width = 3,
      inputPanel(
        selectInput(&quot;Species&quot;, label = &quot;Choose species&quot;,
                    choices = levels(as.factor(iris$Species))
        )
      )
    ),
    
    mainPanel( 
      tabsetPanel(
        tabPanel(
          &quot;Data Table&quot;,
          DTOutput(&quot;iris_datatable&quot;),
          hr()
        )
      )
    )
  )
  
)


server &lt;- function(input, output, session) {
  
  IsColorized &lt;- reactiveVal(isColorized)
  
  dataSubset &lt;- reactiveVal()
  
  observeEvent(input$Species, {
    colorized &lt;- IsColorized()[[input$Species]]
    tableData &lt;- cbind(iris %&gt;% filter(Species == input$Species), colorized)
    dataSubset(tableData)
  })
  
  output$iris_datatable &lt;- renderDT({
    datatable(
      dataSubset(),
      options = list(
        pageLength = 10,
        rowCallback = JS(rowCallback),
        columnDefs = list(
          list(targets = 5:9, visible = FALSE)
        )
      ),
      selection = &#39;none&#39;, 
      editable = list(target = &#39;cell&#39;), 
      rownames= FALSE
    )
  }, server = FALSE)
  
  observeEvent(input$iris_datatable_cell_edit,{
    edit &lt;- input$iris_datatable_cell_edit
    i &lt;- edit$row
    j &lt;- edit$col + 1
    iscolorized &lt;- IsColorized()
    iscolorized[[input$Species]][i, j] &lt;- 1L
    IsColorized(iscolorized)
    runjs(colorizeCell(i, j))
  })
}

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:

确定