简体   繁体   English

Shiny 应用程序中的 DT:使用 UP 和 DOWN 键盘按钮一次选择一行

[英]DT in a Shiny app: select one row at the time with UP and DOWN keyboard's buttons

I have a DT object embed in a Shiny app.我在 Shiny 应用程序中嵌入了一个 DT 对象。 With the code below, I am able to select one row at the time with a left click of the mouse:使用下面的代码,我可以通过鼠标左键一次选择一行:

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

ui <- fluidPage(
  
  fluidRow(
    
    column(width = 12,
           DTOutput(outputId = "table",
                    width = "100%"))
    
  )
  
)

server <- function(input, output, session) {
  
  output$table <- renderDT({
    
    datatable(data = iris,
              selection = "single",
              rownames = FALSE,
              escape = FALSE,
              extension = "KeyTable",
              options = list(pageLength = 10,
                             autoWidth = FALSE,
                             scrollX = TRUE,
                             keys = TRUE,
                             columnDefs = list(list(
                               targets = 4,
                               render = JS(
                                 "function(data, type, row, meta) {",
                                 "return type === 'display' && data != null && data.length > 125 ?",
                                 "'<span title=\"' + data + '\">' + data.substr(0, 125) + '...</span>' : data;",
                                 "}")
                             ))),
              class = "display")
    
  })
  
}

shinyApp(ui = ui,
         server = server)

However, I would like to obtain the same result with the UP and DOWN arrow of the keyboard.但是,我想用键盘的向上和向下箭头获得相同的结果。 In this way, I can select (and automatically deselect) a row only through these two buttons, which is useful when the table is pretty long and there are lots of rows to check.这样,我可以只通过这两个按钮选择(并自动取消选择)一行,这在表格很长并且有很多行要检查时很有用。 Thanks for your help!谢谢你的帮助!

EDIT : I've modified the code to insert the extension "KeyTable" as suggested by silentdevildoll .编辑:我已经修改了代码,按照 silentdevildoll 的建议插入了扩展名“ KeyTable ”。 Although I can move in the table's cells with the keyboard, I am still not able to select them with the UP and DOWN arrow.虽然我可以使用键盘在表格的单元格中移动,但我仍然无法使用向上和向下箭头选择它们。

combined and adapted from different sources but mainly https://laustep.github.io/stlahblog/posts/DTcallbacks.html#select-rows-on-click-and-drag结合并改编自不同的来源,但主要是https://laustep.github.io/stlahblog/posts/DTcallbacks.html#select-rows-on-click-and-drag

Key points:关键点:

  • you need the event key-focus , which is the event triggered because KeyTable already handles the arrow keys to move on the grid.您需要事件key-focus ,这是触发的事件,因为 KeyTable已经处理箭头键在网格上移动。
  • in contrast, key would only handle events that are not handled by key-focus or other built-in KeyTable functionality.相反, key只会处理 key-focus 或其他内置 KeyTable 功能未处理的事件。 https://datatables.net/reference/event/#keytable https://datatables.net/reference/event/#keytable
  • You need server=FALSE in the renderDT call.您需要server=FALSErenderDT调用中。 If you use server-side handling, the indexes will be incorrect if there has been any sorting applied.如果您使用服务器端处理,则如果应用了任何排序,则索引将不正确。
  • Shiny complains about the Select extension which apparently clashes with Shiny's select functionality. Shiny 抱怨Select扩展显然与 Shiny 的选择功能冲突。 However it seems to be working fine.但是,它似乎工作正常。 I just overwrite the existing {outputname}_rows_selected input so the latest entry wins, both click and arrow row selection work.我只是覆盖现有的{outputname}_rows_selected输入,以便最新条目获胜,单击和箭头行选择都有效。
  • Not sure how to better handle initial clicking;不确定如何更好地处理初始点击; it can be that you have to click on the table twice before the keys get activated (seen by the blue highlight on the selected cell)可能是您必须在激活键之前单击表格两次(通过所选单元格上的蓝色突出显示)
library(shiny)
library(DT)

js_select_dt <- c(
  "var dt = table.table().node();",
  "var tblID = $(dt).closest('.datatables').attr('id');",
  "var inputName = tblID + '_rows_selected'",
  "var incrementName = tblID + '_rows_selected2_increment'",
  "table.on('key-focus', function(e, datatable, cell, originalEvent){",
  "  if (originalEvent.type === 'keydown'){",
  "    table.rows().deselect(); ",
  "    table.row(cell[0][0].row).select();",
  "    row = table.rows({selected: true})",
  # Note: this ID is zero-based so add one
  "    Shiny.setInputValue(inputName, [parseInt(row[0]) + 1]);",
  "  }",
  "});"
)


ui <- fluidPage(
  textOutput("selectedRow"),
  DT::DTOutput("irisTable")
)

server <- function(input, output) {
  output$irisTable<- DT::renderDT({
    iris %>%
      datatable(
        # This datatable uses both shiny's select for conventional selection
        # and keytable + select for selection by keyboard (callback js_select_dt, see above).
        # The keyboard-selected row just overwrites the regular input$peaksTable_rows_selected
        # field.
        selection = "single",
        editable = FALSE, 
        callback = JS(js_select_dt),
        extensions = c("KeyTable", "Select"),
        options = list(
          keys = TRUE,
          # keys = list(keys = c(38, 40))
          select = TRUE
        )
      )
  }, server=FALSE)
  
  output$selectedRow <- renderText(input$irisTable_rows_selected)
}

runApp(shinyApp(ui, server))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM