如何在 Shiny eventReactive 处理程序中侦听多个事件表达式
Posted
技术标签:
【中文标题】如何在 Shiny eventReactive 处理程序中侦听多个事件表达式【英文标题】:How to listen for more than one event expression within a Shiny eventReactive handler 【发布时间】:2016-04-16 09:04:40 【问题描述】:我想要两个不同的事件来触发我的应用程序中各种绘图/输出所使用的数据的更新。一个是正在单击的按钮 (input$spec_button
),另一个是正在单击的点上的点 (mainplot.click$click
)。
基本上,我想同时列出两者,但我不确定如何编写代码。这是我现在拥有的:
在 server.R 中:
data <- eventReactive(mainplot.click$click | input$spec_button,
if(input$spec_button)
# get data relevant to the button
else
# get data relevant to the point clicked
)
但是 if-else 子句不起作用
Error in mainplot.click$click | input$spec_button :
operations are possible only for numeric, logical or complex types
--> 有什么动作组合函数可以用于mainplot.click$click | input$spec_button
子句吗?
【问题讨论】:
你能检查 !is.null(input$spec_button) 的输出吗? 【参考方案1】:我知道这是旧的,但我有同样的问题。我终于弄明白了。您在大括号中包含一个表达式并简单地列出事件/反应对象。我的(未经证实的)猜测是,shiny 只是对这个表达式块执行与标准 reactive
块相同的反应指针分析。
observeEvent(
input$spec_button
mainplot.click$click
1
, ... )
编辑
已更新以处理表达式中最后一行返回 NULL 的情况。只需返回一个常量值。
【讨论】:
更改已接受的答案,因为它似乎比我原来的解决方案更好。 你能确定是哪个事件被触发了吗? 我不知道。在少数情况下,我通过在单独的变量中跟踪它们并自己进行比较以查看哪些发生了变化,从而做到了这一点。但它很丑。可能最好将主代码放在一个函数中,然后有两个调用 fn 的 observeEvents,然后为每个事件执行特定的操作。 只是一个警告:observeEvent
默认使用ignoreNULL = TRUE
,这意味着如果mainplot.click$click
(返回值)是NULL
,则处理程序将永远即使input$spec_button
改变了也会调用。我会推荐类似@JustAnother 的答案,以防止落入这个陷阱。
另一个警告:在我的测试中,我发现这个括号语法 (
) 要求每个事件都在自己的换行符上,否则它会尽快失败并显示“解析中的错误...”解析器遇到第二个事件。例如,全部在一行:observeEvent(input$spec_button mainplot.click$click, ...)
失败。 @JustAnother's answer using S3 Generic combine syntax (c()
) 无论换行如何都有效。【参考方案2】:
还有:
observeEvent(c(
input$spec_button,
mainplot.click$click
), ... )
【讨论】:
虽然这看起来与@DuncanBrown 的答案非常相似,但我发现了一种情况,其中 2 个操作按钮都触发了一个模式,这是有效的,而
版本没有。我无法解释为什么会这样。
在@Duncan Brown 的回答中添加了关于这个答案有何不同(以及更好的 IMO)的评论
这个对我不起作用 - 我收到一个错误(闪亮的 1.0.5)
有没有办法找出触发了哪个事件?假设我有两个按钮,input$button1
和 input$button2
,它们做的事情非常相似,只是索引不同。我想避免因为我不知道索引而多次复制代码。谢谢!【参考方案3】:
我已经通过创建反应性对象并在事件更改表达式中使用它来解决这个问题。如下:
xxchange <- reactive(
paste(input$filter , input$term)
)
output$mypotput <- eventReactive( xxchange(),
...
...
...
)
【讨论】:
这是一个非常好的答案,可以从更多解释中受益。虽然接受的答案更直接,使其更适合基本程序,但这个答案更适合大型和复杂的代码。答案中似乎缺少两点(1)粘贴(或列表)将两个事件放在同一行,使代码更紧凑。 (2) 如果有多个侦听器正在侦听同一组事件,则响应式对象可以省去一遍又一遍地重复相同的两个事件的工作量。【参考方案4】:这是我想出的解决方案:基本上,创建一个空的 reactiveValues
数据持有者,然后根据两个单独的 observeEvent
实例修改其值。
data <- reactiveValues()
observeEvent(input$spec_button,
data$data <- get.focus.spec(input=input, premise=premise,
itemname=input$dropdown.itemname, spec.info=spec.info)
)
observeEvent(mainplot.click$click,
data$data <- get.focus.spec(input=input, premise=premise, mainplot=mainplot(),
mainplot.click_focus=mainplot.click_focus(),
spec.info=spec.info)
)
【讨论】:
list(mainplot.click$click, input$spec_button)
也适用于 OP 的方式。【参考方案5】:
这仍然可以使用 eventReactive 来完成,方法是将您的操作放在一个向量中。
eventReactive(
c(input$spec_button, mainplot.click$click),
... )
【讨论】:
【参考方案6】:这里的想法是创建一个反应函数,它将执行您想要在 observeEvent 中传递的条件,然后您可以传递这个反应函数来检查语句的有效性。例如:
validate_event <- reactive(
# I have used OR condition here, you can use AND also
req(input$spec_button) || req(mainplot.click$click)
)
observeEvent(validate_event(),
...
)
继续编码!
【讨论】:
以上是关于如何在 Shiny eventReactive 处理程序中侦听多个事件表达式的主要内容,如果未能解决你的问题,请参考以下文章
Shiny:observeEvent 和 eventReactive 有啥区别?
通过编辑表格和/或 eventReactive 来更新handsontable
闪亮的 SelectInput 和 SelectizeInput