R语言 自动滚动到datatable中的选定行

kokeuurv  于 2023-06-19  发布在  其他
关注(0)|答案(1)|浏览(94)

我正在构建一个Shiny应用程序,在其中呈现来自sf包的nc县的LeafletMap,以及包含县所有信息的数据表。我已经把Map上的县层和数据表“链接”起来了,这样就可以通过在Map上或数据表中单击县来选择县。
下面是我的应用程序的代码:

# Load packages ----
library(shiny)
library(sf)
library(hash)

# User interface ----
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(width=4,
      style = "height: 96vh; overflow-y: auto",
      p("in my actual app there are a bunch of buttons and selection inputs here that are used to generate the spatial dataframe object shown in the map")
    ),
    mainPanel(width=8,
      tags$style(type = "text/css", "#map {height: calc(47vh) !important;}"),
      leafletOutput("map"),
      dataTableOutput(outputId = "table")  
    )
  )
)

# Server logic ----
server <- function(input, output) {
  nc <- st_read(system.file("shape/nc.shp", package="sf")) %>%
    st_transform(crs=4326)
  
  output$map <- renderLeaflet({
    leaflet() %>%
      setView(-79, 35, 7) %>% 
      addTiles(group = "OpenStreetMap") %>%
      addPolygons(data = nc, 
                  color="#000000",
                  layerId = ~CNTY_ID,
                  group="Counties",
                  highlightOptions = highlightOptions(color = "white", 
                                                      weight = 2,
                                                      opacity=0.7,
                                                      bringToFront = TRUE)) %>%
      addLayersControl(
        baseGroups = c("OpenStreetMap"),
        overlayGroups = c("Counties"),
        options = layersControlOptions(collapsed = FALSE)
      )
  })
  
  output$table <- DT::renderDataTable({DT::datatable(nc,
                                                     selection= "single",
                                                     options = list(scrollX = TRUE,
                                                                    scrollY = "47vh",
                                                                    dom = 't',
                                                                    paging = FALSE))})
  
  id_dict <- hash()
  for (i in 1:nrow(nc)) {
    id_dict[[as.character(nc[i,]$CNTY_ID)]] <- i
  }
  
  observeEvent(input$map_shape_click, {
    clicked_county <- input$map_shape_click$id
    clicked_id <- id_dict[[as.character(clicked_county)]]
    change_selection(clicked_id, clicked_county, from_table = FALSE)
  })
  
  observeEvent(input$table_rows_selected, ignoreNULL = FALSE, {
    clicked_id <- input$table_rows_selected
    clicked_county <- nc[input$table_rows_selected,]$CNTY_ID
    print(clicked_id)
    change_selection(clicked_id, clicked_county, from_table = TRUE)
  })
  
  change_selection <- function(clicked_id, clicked_county, from_table){
    if(!from_table) {
      dataTableProxy("table") %>%
        selectRows(NULL) %>%
        selectRows(which(input$table_rows_all == clicked_id))
        # SOME CODE HERE TO SCROLL TO THE SELECTED ROWS
    } else if (from_table) {  
      leafletProxy("map") %>%
        removeShape("highlighted_county") %>%
        addPolygons(data = nc[nc$CNTY_ID==clicked_county,],
                    layerId = "highlighted_county",
                    weight=6,
                    opacity = 1,
                    color="white"
        )
    }
  }
  
  

}

# Run the app
shinyApp(ui, server)

table中单击县以选择县时,map上的相应多边形将突出显示。当在map上选择一个县时,会选择table中的相应行,* 但是 * 我希望table也能自动滚动到相应的行,以便在Map上单击时自动进入视图。我感觉这只需要在我的change_selection()函数中再做一步,但我可能需要使用JavaScript(例如:类似table().row().scrollTo(clicked_id)),但不知道如何实现。
有什么想法吗

ruyhziif

ruyhziif1#

首先,我们在应用程序中添加以下JavaScript代码:

js <- '
  Shiny.addCustomMessageHandler("scrollTo", function(id) {
    $("body").trigger("myCustomEvent", id);
  }); 
'

我们将使用此代码将点击的id发送到JavaScript,这将触发一个包含点击id数据的事件myCustomEvent
按如下方式添加此代码:

ui <- fluidPage(
  tags$script(
    HTML(js)
  ),
  sidebarLayout(
    ......

添加session作为server函数的第三个参数,并使用以下代码将点击的id发送到JavaScript:

change_selection <- function(clicked_id, clicked_county, from_table){
    if(!from_table) {
      session$sendCustomMessage("scrollTo", clicked_id)
    } else if (from_table) {  
      leafletProxy("map") %>%
        removeShape("highlighted_county") %>%
        addPolygons(data = nc[nc$CNTY_ID==clicked_county,],
                    layerId = "highlighted_county",
                    weight=6,
                    opacity = 1,
                    color="white"
        )
    }
  }

现在我们将在DT表中侦听此事件。我们使用扩展名Select以编程方式选择一行,使用扩展名Scroller滚动到一行:

output$table <- renderDT({
    datatable(nc,
              callback = JS(callback),
              extensions = c("Select", "Scroller"),
              selection = "none",
              options = list(
                scrollX = TRUE,
                scrollY = "200px",
                scrollCollapse = TRUE,
                dom = "frtip",
                paging = TRUE,
                select = TRUE,
                scroller = TRUE
              )
    )
  }, server = FALSE)

下面是DT回调:

callback <- '
  $("body").on("myCustomEvent", function(e, id) {
    table.row(id).select();
    table.row(id).scrollTo();
  })
'

它在RStudio浏览器中不起作用,但它在普通浏览器中起作用,甚至在Edge中也是如此:

编辑

Scroller扩展的scrollTo方法似乎不起作用。所以这里有另一种方法。回调:

callback <- '
  $("body").on("myCustomEvent", function(e, id) {
    table.row(id).select();
    table.row(id).nodes().to$().get(0).scrollIntoView();
  })
'

DT表:

output$table <- renderDT({
    datatable(nc,
              callback = JS(callback),
              extensions = "Select",
              selection = "none",
              options = list(
                scrollX = TRUE,
                scrollY = "200px",
                scrollCollapse = TRUE,
                dom = "frtip",
                paging = FALSE,
                select = TRUE
              )
    )
  }, server = FALSE)

相关问题