渲染函数的反应参数
Reactive argument to render functions
我在 flexdashboard 中有一个 table,它的列数可以改变。我可以即时计算列的对齐方式(默认对齐方式将 .45
视为字符向量,因此左对齐值,尽管它是一个数字并且应该右对齐)。问题是我无法将此对齐作为 align
的值传回 renderTable
,因为它是一个反应值。
如何将反应式对齐传递回 renderTable
函数的 align
参数? (或者让我用反应式对齐渲染 table 的替代方案)
MWE
---
title: "test"
output: flexdashboard::flex_dashboard
runtime: shiny
---
```{r}
library(flexdashboard)
library(shiny)
```
Inputs {.sidebar}
-------------------------------------
```{r}
selectInput(
"ncols",
label = "How many columns?",
choices = 1:5,
selected = 5
)
```
Column
-------------------------------------
### Test
```{r}
nc <- reactive({input$ncols})
aln <- reactive({substring('lllrr', 1, nc())})
renderTable({
x <- CO2[1:5, seq_len(nc()), drop = FALSE]
x[, 1] <- as.character(x[, 1])
x[3, 1] <- '<b>Mc1</b>'
x
}, align = aln(), sanitize.text.function = function(x) x)
```
结果:
Warning: Error in .getReactiveEnvironment()$currentContext: Operation not
allowed without an active reactive context. (You tried to do something
that can only be done from inside a reactive expression or observer.)
尝试将 aln()
包装在 renderText(...)
中,即
renderTable({
x <- CO2[1:5, seq_len(nc()), drop = FALSE]
x[, 1] <- as.character(x[, 1])
x[3, 1] <- '<b>Mc1</b>'
x
}, align = renderText(aln()),
sanitize.text.function = function(x) x)
首先,发生的具体错误是正确的。函数 renderTable
只能在其第一个参数 renderTable({ ... }, ...)
中包含反应式表达式。所有其他事物都必须是普通对象。因此,在常规环境中放置一个反应值 aln()
实际上就是在其中放置一个 reactive
。或者,从 reactive
本身的角度来看,它是在 没有活动的反应上下文 的情况下评估的,就像它在错误消息中所说的那样。
一种使这些东西也具有反应性的解决方法是 renderTable
的包装器,即 renderUI
。在 renderUI
中,我们可以反应性地塑造包括对齐在内的整个 table 渲染。 (解决方案部分改编自 here。)
这是您必须将 renderTable
替换为:
renderUI({
output$table <- renderTable({
x <- CO2[1:5, seq_len(isolate(nc())), drop = FALSE]
x[, 1] <- as.character(x[, 1])
x[3, 1] <- '<b>Mc1</b>'
x
}, align = aln(), sanitize.text.function = function(x) x)
tableOutput("table")
})
快速解释: 使用 output
变量就像您在常规闪亮环境中那样做,如果不是在 markdown 中的话。 renderUI
将呈现的是对 renderTable
的引用,我们每次都会从头开始重新创建它。
注:我在renderTable
里面用了一个isolate
。原因如下:renderTable
是被动的,并且会在 nc()
发生变化时更新。但这可能发生在周围的 renderUI
对变化做出反应之前。您会看到,在此中间步骤中,renderTable
尝试绘制具有不同列数的 data.frame
,但 align
仍然是之前的那个。抛出错误,因为它们不匹配。隔离内部 nc()
会阻止内部 renderTable
更新。但这没关系,因为一旦轮到更新,外部 renderUI
无论如何都会这样做。
我在 flexdashboard 中有一个 table,它的列数可以改变。我可以即时计算列的对齐方式(默认对齐方式将 .45
视为字符向量,因此左对齐值,尽管它是一个数字并且应该右对齐)。问题是我无法将此对齐作为 align
的值传回 renderTable
,因为它是一个反应值。
如何将反应式对齐传递回 renderTable
函数的 align
参数? (或者让我用反应式对齐渲染 table 的替代方案)
MWE
---
title: "test"
output: flexdashboard::flex_dashboard
runtime: shiny
---
```{r}
library(flexdashboard)
library(shiny)
```
Inputs {.sidebar}
-------------------------------------
```{r}
selectInput(
"ncols",
label = "How many columns?",
choices = 1:5,
selected = 5
)
```
Column
-------------------------------------
### Test
```{r}
nc <- reactive({input$ncols})
aln <- reactive({substring('lllrr', 1, nc())})
renderTable({
x <- CO2[1:5, seq_len(nc()), drop = FALSE]
x[, 1] <- as.character(x[, 1])
x[3, 1] <- '<b>Mc1</b>'
x
}, align = aln(), sanitize.text.function = function(x) x)
```
结果:
Warning: Error in .getReactiveEnvironment()$currentContext: Operation not
allowed without an active reactive context. (You tried to do something
that can only be done from inside a reactive expression or observer.)
尝试将 aln()
包装在 renderText(...)
中,即
renderTable({
x <- CO2[1:5, seq_len(nc()), drop = FALSE]
x[, 1] <- as.character(x[, 1])
x[3, 1] <- '<b>Mc1</b>'
x
}, align = renderText(aln()),
sanitize.text.function = function(x) x)
首先,发生的具体错误是正确的。函数 renderTable
只能在其第一个参数 renderTable({ ... }, ...)
中包含反应式表达式。所有其他事物都必须是普通对象。因此,在常规环境中放置一个反应值 aln()
实际上就是在其中放置一个 reactive
。或者,从 reactive
本身的角度来看,它是在 没有活动的反应上下文 的情况下评估的,就像它在错误消息中所说的那样。
一种使这些东西也具有反应性的解决方法是 renderTable
的包装器,即 renderUI
。在 renderUI
中,我们可以反应性地塑造包括对齐在内的整个 table 渲染。 (解决方案部分改编自 here。)
这是您必须将 renderTable
替换为:
renderUI({
output$table <- renderTable({
x <- CO2[1:5, seq_len(isolate(nc())), drop = FALSE]
x[, 1] <- as.character(x[, 1])
x[3, 1] <- '<b>Mc1</b>'
x
}, align = aln(), sanitize.text.function = function(x) x)
tableOutput("table")
})
快速解释: 使用 output
变量就像您在常规闪亮环境中那样做,如果不是在 markdown 中的话。 renderUI
将呈现的是对 renderTable
的引用,我们每次都会从头开始重新创建它。
注:我在renderTable
里面用了一个isolate
。原因如下:renderTable
是被动的,并且会在 nc()
发生变化时更新。但这可能发生在周围的 renderUI
对变化做出反应之前。您会看到,在此中间步骤中,renderTable
尝试绘制具有不同列数的 data.frame
,但 align
仍然是之前的那个。抛出错误,因为它们不匹配。隔离内部 nc()
会阻止内部 renderTable
更新。但这没关系,因为一旦轮到更新,外部 renderUI
无论如何都会这样做。