R Shiny - 使用javascript回调滚动到给定的数据表行

Posted

技术标签:

【中文标题】R Shiny - 使用javascript回调滚动到给定的数据表行【英文标题】:R Shiny - Scrolling to a given row of datatable with javascript callback 【发布时间】:2018-06-03 08:19:00 【问题描述】:

我遇到了数据表和闪亮的问题,特别是在 flexdashboard 中,但我认为这无关紧要。

当我单击绘图中的相应点时,我想滚动到数据表中的给定行。但是,我遇到的最小问题是“简单地”滚动到任何行。我可以使用带有 initComplete 选项的 javascript 选择一行,但 scrollTo() 不会为我做任何事情。

查看上一个问题Scroll to specific row in Datatable API,我得到了这个示例https://codepen.io/anon/pen/KWmpjj。它展示了您可以与 initComplete 一起使用的 javascript 函数,但这不是用 R/Shiny 制作的。具体来说,您会发现以下适用于小型数据表的选项:

initComplete: function () 
        this.api().row(14).scrollTo();
      $(this.api().row(14).node()).addClass('selected');
    

因为我的目标是在 flexdashboard 中使用它,所以我有一个 R markdown 格式的最小示例。使用随机数据对DT::renderDataTable 进行非常标准的调用。我不明白为什么this.api().table().row(15).scrollTo(); 不会做任何事情。我添加了一个警报,以确认 initComplete 的 JavaScript 确实运行了。

---
title: "Scroll to row in datatable"
date: "20 december 2017"
output: html_document
runtime: shiny
---

```r setup, include=FALSE
knitr::opts_chunk$set(echo = TRUE)
```

## Datatable automatically scroll to given row
The goal is to have a datatable rendered in a flexdashboard. Upon selecting a point in a scatter plot, the corresponding row in the table gets selected and needs to be scrolled into view. Selecting a row by clicking a point in a plot (with ggplot) works, but scrolling will not.

Preferably without using shinyApp(), since scrolling is a JavaScript functionality rather than a shiny one (?).

```r
library(dplyr)
library(DT)

# Generate random data
df <- data.frame(matrix(runif(1000), ncol = 5))

# Render datatable with shiny
DT::renderDataTable(
  DT::datatable(df,
  extensions = 'Scroller',
  # selection = 'single',                 # Eventually only allow single selection
  escape = FALSE,
  # callback = JS('this.api().row(15).scrollTo();'),       # Attempt to use callback instead
  options = list(scrollX = TRUE,
                 scrollY = 200,
                 paging = FALSE,
                 initComplete  = JS('function() 
                                   $(this.api().table().row(15).node()).addClass("selected");
                                   this.api().table().row(15).scrollTo();
                                  alert("scrolled");'))),
  server = TRUE) # Setting server = TRUE results in the selection with initComplete breaking

```

我注意到的是,如果您滚动 previously linked example 中的表格,底部的文本实际上会更新并显示“显示 20 个条目中的 1 到 6 个”或“显示 20 个条目中的 6 到 11 个”等. 这不会发生在我的示例数据表中,它总是显示 200 个条目中的 1 到 200 个。这让我认为它不会滚动到指定的行,因为一切都已经“在视图中”,即使它不是真的。

【问题讨论】:

【参考方案1】:

您需要在datatable() options 参数中设置scroller = TRUEpaging = TRUE。这对我有用:

---
title: "Scroll to row in datatable"
date: "20 december 2017"
output: html_document
runtime: shiny
---

```r setup, include=FALSE
knitr::opts_chunk$set(echo = TRUE)
```

## Datatable automatically scroll to given row
The goal is to have a datatable rendered in a flexdashboard. Upon selecting a point in a scatter plot, the corresponding row in the table gets selected and needs to be scrolled into view. Selecting a row by clicking a point in a plot (with ggplot) works, but scrolling will not.

Preferably without using shinyApp(), since scrolling is a JavaScript functionality rather than a shiny one (?).

```r
library(dplyr)
library(DT)

# Generate random data
df <- data.frame(matrix(runif(1000), ncol = 5))

# Render datatable with shiny
DT::renderDataTable(
  DT::datatable(df,
  extensions = 'Scroller',
  # selection = 'single',                 # Eventually only allow single selection
  escape = FALSE,
  # callback = JS('this.api().row(15).scrollTo();'),       # Attempt to use callback instead
  options = list(scrollX = TRUE,
                 scrollY = 200,
                 paging = TRUE,
                 scroller = TRUE,
                 initComplete  = JS('function() 
                                   $(this.api().table().row(15).node()).addClass("selected");
                                   this.api().table().row(15).scrollTo();
                                  alert("scrolled");'))),
  server = TRUE) # Setting server = TRUE results in the selection with initComplete breaking

【讨论】:

是的,就是这样,但它还不能顺利运行。滚动到第 15 行有效 - 但由于某种原因我失去了行选择本身。奇怪的是——如果我想滚动到例如第 50 行,它在查看器中不起作用,但它在浏览器中起作用。查看器滚动到第 33 行或非第 50 行。此外,如果我尝试滚动到第 100 行,它在浏览器或查看器中都不起作用(在此处使用 Microsoft Edge) 我观察到与@LodewicVanTwillert 完全相同的行为。它移动到某一行,但不是指定的行。此外,该行从未被选中。 此问题的任何解决方案。我也面临同样的情况。【参考方案2】:

我不知道为什么DataTables 的.scrollTo() 方法不起作用,但我只是在HTML 节点上测试了原生的.scrollIntoView() 方法,它对我来说效果很好。我改变了你的

this.api().table().row(15).scrollTo();

this.api().table().row(15).node().scrollIntoView();

完整示例:

---
title: "Scroll to row in datatable"
date: "20 december 2017"
output: html_document
runtime: shiny
---

```r setup, include=FALSE
knitr::opts_chunk$set(echo = TRUE)
```

## Datatable automatically scroll to given row
The goal is to have a datatable rendered in a flexdashboard. Upon selecting a point in a scatter plot, the corresponding row in the table gets selected and needs to be scrolled into view. Selecting a row by clicking a point in a plot (with ggplot) works, but scrolling will not.

Preferably without using shinyApp(), since scrolling is a JavaScript functionality rather than a shiny one (?).

```r
library(dplyr)
library(DT)

# Generate random data
df <- data.frame(matrix(runif(1000), ncol = 5))

# Render datatable with shiny
DT::renderDataTable(
  DT::datatable(df,
  extensions = 'Scroller',
  # selection = 'single',                 # Eventually only allow single selection
  escape = FALSE,
  # callback = JS('this.api().row(15).scrollTo();'),       # Attempt to use callback instead
  options = list(scrollX = TRUE,
                 scrollY = 200,
                 paging = FALSE,
                 initComplete  = JS('function() 
                                   $(this.api().table().row(15).node()).addClass("selected");
                                   this.api().table().row(15).node().scrollIntoView();
                                  '))),
  server = TRUE) # Setting server = TRUE results in the selection with initComplete breaking

```

【讨论】:

不是Pagination must be enabled for Scroller 吗? 出于某种原因,将row-1 与.scrollIntoView() 一起使用对我来说效果更好,但也是一个很好的解决方案。【参考方案3】:

你也可以用这个方法

this.api().table().scroller.toPosition(15);

【讨论】:

以上是关于R Shiny - 使用javascript回调滚动到给定的数据表行的主要内容,如果未能解决你的问题,请参考以下文章

R Shiny - extendShinyjs 解析提供的 JavaScript 代码时出错

渲染 JavaScript 会破坏 R Shiny DT (DataTable) 中的页面导航和反应功能

R Shiny Pass 文件列表到 Javascript 下载器

R Shiny:如何从数据表中的自定义按钮调用 JavaScript 函数

如何在 r shiny 中使用 JS 数据表 API?

R / Shiny selectInput小部件大小