css 在DT::datatable中使用多种选择颜色?

tzdcorbm  于 2023-02-17  发布在  其他
关注(0)|答案(2)|浏览(124)

我已设置:

output$tableId <- 
   DT::renderDataTable({DT::datatable(..., selection = "multiple")})

我想选择的背景色根据它的第一个选择,或第二个,等等。
应该可以使用length(input$tableId_rows_selected)(描述为here)来获得这种行为?我猜结合创建一些CSS来修改它:

.table.dataTable tbody td.active, .table.dataTable tbody tr.active td {
   background-color: #007bff;
   color: white;
}

我对CSS、HTML和JavaScript知之甚少,所以我觉得这些东西很难。

    • 编辑日期:2022年2月14日:**

在@StéphaneLaurent下面的初步回答之后,我想稍微改变一下我的问题:
我最喜欢的逻辑是:
1.我们有m种独特的颜色。n < m种以前的行已被选中。
1.第n+1行被选中,然后以第n+1颜色着色,并保持该颜色直到取消选中。
1.当前选择m行时,不可能再选择其他行。另外,我还对以下内容感兴趣:当第m+1行被选中时,它会被涂上第一种颜色,而其他占据这种颜色的行会被取消选中。m+1行现在被选中,而当第m+2行被选中时,它会被涂上第二种颜色,而其他占据这种颜色的行会被取消选中,依此类推。
此外:

  • 由于我的应用程序将通过网站上的iframe运行,并且应用程序的底层数据将有1000万到1亿个观察值,我认为DT::renderDataTable({...}, server = TRUE)的解决方案会很好。
  • 我还希望该解决方案能够与DT::datatable(..., selection = list(mode = "multiple", selected = 1:3, target = "row"))选项一起使用。

我将尝试实现上述使用@StéphaneLaurent答案,结合工具@YihuiXie说明here(应用程序从页面链接较早).

wwtsj6pe

wwtsj6pe1#

如果您使用以下CSS,则第一行将为红色(如果您选择它),第二行将为绿色,第三行将为蓝色:

#dtable tbody tr.selected:nth-of-type(1) td {
  box-shadow: inset 0 0 0 9999px red;
}
#dtable tbody tr.selected:nth-of-type(2) td {
  box-shadow: inset 0 0 0 9999px green;
}
#dtable tbody tr.selected:nth-of-type(3) td {
  box-shadow: inset 0 0 0 9999px blue;
}

这里dtable是id。

library(shiny)
library(DT)

css <- "
#dtable tbody tr.selected:nth-of-type(1) td {
  box-shadow: inset 0 0 0 9999px red;
}
#dtable tbody tr.selected:nth-of-type(2) td {
  box-shadow: inset 0 0 0 9999px green;
}
#dtable tbody tr.selected:nth-of-type(3) td {
  box-shadow: inset 0 0 0 9999px blue;
}
"

ui <- fluidPage(
  tags$head(
    tags$style(
      HTML(css)
    )
  ),
  br(), br(),
  DTOutput("dtable")
)

server <- function(input, output, session) {
  
  output[["dtable"]] <- renderDT({
    datatable(iris, selection = "multiple")
  })
  
}

shinyApp(ui, server)

下面是如何使用sass包为100行生成随机颜色的CSS。保存下面的scss文件,比如mystyle.scss

$s-min: 20;
$s-max: 70;
$l-min: 30;
$l-max: 90;

@for $i from 1 through 100 {
  #dtable tbody tr.selected:nth-of-type(#{$i}) td {
    box-shadow: inset 0 0 0 9999px hsl(random(360),$s-min+random($s-max+-$s-min),$l-min+random($l-max+-$l-min));
  }
}

现在将其编译为CSS文件:

library(sass)
sass(sass_file("mystyle.scss"), output = "mystyle.css")

将文件mystyle.css放入应用程序的www子文件夹中,然后将其包含在应用程序中,如下所示:

ui <- fluidPage(
  tags$head(
    tags$link(
      href = "mystyle.css", rel = "stylesheet"
    )
  ),
  ......

编辑:jQuery解决方案

library(shiny)
library(DT)

js <- '
var colors = ["red", "green", "blue", "yellow", "purple"];
table.on("select", function(e, dt, type, indexes) {
  var count = table.rows({selected: true}).count();
  for(var i = 0; i < count; i++) {
    $("#dtable tbody tr.selected").eq(i).find("td").css(
      "box-shadow", "inset 0 0 0 9999px " + colors[i]
    );
  }
}).on("deselect", function(e, dt, type, indexes) {
  for(var i = 0; i < indexes.length; i++) {
    $("#dtable tbody tr").eq(indexes[i]).find("td").css(
      "box-shadow", ""
    );
  }
  var count = table.rows({selected: true}).count();
  for(var i = 0; i < count; i++) {
    $("#dtable tbody tr.selected").eq(i).find("td").css(
      "box-shadow", "inset 0 0 0 9999px " + colors[i]
    );
  }
});
'

ui <- fluidPage(
  br(), br(),
  DTOutput("dtable")
)

server <- function(input, output, session) {
  
  output[["dtable"]] <- renderDT({
    datatable(
      iris, 
      extensions = "Select",
      selection = "none", 
      callback = JS(js),
      options = list(
        "select" = "multi" 
      )
    )
  }, server = FALSE)
  
}

EDIT:更正之前的编辑

下面是正确的JS代码:

js <- '
var colors = ["red", "green", "blue", "yellow", "purple"];
var stack = [];
table.on("select", function(e, dt, type, indexes) {
  stack.push(indexes[0]);
  for(var i = 0; i < stack.length; i++) {
    $("#dtable tbody tr").eq(stack[i]).find("td").css(
      "box-shadow", "inset 0 0 0 9999px " + colors[i]
    );
  }
}).on("deselect", function(e, dt, type, indexes) {
  var i0 = stack.indexOf(indexes[0]);
  $("#dtable tbody tr").eq(stack[i0]).find("td").css(
    "box-shadow", ""
  );
  stack.splice(i0, 1);
  for(var i = 0; i < stack.length; i++) {
    $("#dtable tbody tr").eq(stack[i]).find("td").css(
      "box-shadow", "inset 0 0 0 9999px " + colors[i]
    );
  }
});
'

EDIT:不带“Select”扩展名

js <- '
var colors = ["red", "green", "blue", "yellow", "purple"];
var stack = [];
table.on("click", "tr", function() {
  var $rows = $("#dtable tbody tr"); // SIMONSIMON I moved this line
  var $row = $(this);
  var idx = $row.index();
  if($row.hasClass("selected")) {
    stack.push(idx);
    for(var i = 0; i < stack.length; i++) {
      $rows.eq(stack[i]).find("td").css(
        "box-shadow", "inset 0 0 0 9999px " + colors[i]
      );
    }
  } else {
    var i0 = stack.indexOf(idx);
    $rows.eq(stack[i0]).find("td").css(
      "box-shadow", ""
    );
    stack.splice(i0, 1);
    for(var i = 0; i < stack.length; i++) {
      $rows.eq(stack[i]).find("td").css(
        "box-shadow", "inset 0 0 0 9999px " + colors[i]
      );
    }
  }
});
'

......

  output[["dtable"]] <- renderDT({
    datatable(
      iris, 
      selection = "multiple", 
      callback = JS(js)
    )
  }, server = TRUE)
ef1yzkbh

ef1yzkbh2#

虽然从技术上讲,这并没有达到我最初的要求(即动态地改变选择颜色),但从最终用户的Angular 来看,这种实现的结果在视觉上看起来很相似。
该解决方案背后的思想是跟踪行选择计数器,通过代理更新表,并应用条件格式。

library(shiny)
library(data.table)
library(DT)

data(iris)
iris <- suppressWarnings(cbind(as.data.table(iris),
                               currently_selected = numeric(),
                               selected_as_nr     = numeric(),
                               overwrite          = numeric()))

ui <- fluidPage(
  dataTableOutput("table"),
)

server <- function(input, output, session) {
  
  iris[, currently_selected := 0]
  iris[, selected_as_nr     := NA]
  iris[, overwrite          := 0]
  output$table <- DT::renderDataTable({
    DT::datatable(iris,
                  selection = list(mode = "multiple",
                                   selected = 1,
                                   target = "row")) %>%
      formatStyle("Sepal.Length",
                  "selected_as_nr",
                  backgroundColor = styleEqual(0:4, c("green",
                                                      "red",
                                                      "black",
                                                      "blue",
                                                      "yellow")))
  })
  
  proxy <- dataTableProxy(outputId = "table")
  
  observeEvent(input$table_rows_selected, {
    
         new_selected_row <- input$table_rows_selected[1]
    iris[new_selected_row, currently_selected := (currently_selected + 1) %% 2]
    
    if (iris[new_selected_row, currently_selected] == 1) {
      
      new_selection_nr <- suppressWarnings(iris[, min(setdiff(0:4, unique(selected_as_nr)))])
      
      if (new_selection_nr != "Inf") {
        
        iris[, overwrite := 0]
        iris[new_selected_row, selected_as_nr := new_selection_nr] 
        
      } else {
        
        overwrite <- iris[, unique(overwrite)]
        
        iris[selected_as_nr == overwrite, currently_selected := 0]
        iris[selected_as_nr == overwrite, selected_as_nr := NA]
        
        iris[new_selected_row, selected_as_nr := overwrite]
        
        iris[, overwrite := (overwrite + 1) %% 5]
      
      }
      
    } else {
      
      iris[new_selected_row, selected_as_nr := NA]
      
    }
    
    DT::replaceData(proxy, iris)
    
  })
  
}

shinyApp(ui, server)

相关问题