由函数内部创建的旧 observeEvents 触发的不需要的弹出风暴

Unwanted popup storm triggered by old observeEvents created inside a function

如何在数据更改时阻止函数内创建的观察者多次存在?

更新: - 进一步简化 github 上的应用程序以便于测试。 - 一直在尝试使用 destroy ----

我制作了一个应用程序,在我的程序中需要多个(10 个左右)版本的情节,因此我编写了 2 个函数:

当用户点击第一个图中的一个点时,这些对话框会打开。

此函数的简化版本如下所示:

mypopup <- function(THEDATAFRAME, THEPLOT, THEGROUP, THEPULSEFRAME) {
..... bla bla lots more code in real app.....
  ..... one example of an observer with only 1 of the arguments needed for this one
  observeEvent(input[[paste("Close", THEPLOT, sep ='.')]], {
    removeModal()
  }, ignoreInit = T)

}

函数*1在创建或加载相应的数据框时调用,并在数据发生变化时再次调用。

我面临的问题是,在数据被更改并且用户点击弹出窗口的某个点后,所有观察者都会触发两次。如果数据再次更改,弹出窗口会触发 3 次,依此类推。 此外,基于旧数据的弹出窗口不理解图中现在有超过 1 个集群,因此如果您单击集群 2 或 3,错误/ NA 图等。

报表

我已经创建了一个精简的工作代码示例以及一些文件 运行 它可以在以下 github link 中找到: https://github.com/madmark81/Observer-Madness

脚注

1 我之所以将它写成函数,是因为我每次都在我的主应用程序中多次应用这种绘图和弹出窗口的组合,具体取决于独特的组合基本数据帧和脉冲数据帧以及包含组 ID 和组名称的列。

2 Maximilian 提出了将观察者分配给变量的想法。但是这个实现似乎必须在 mypopup 函数之外完成,而且我无法让它在使用超过 1 个输入参数的观察者上工作,这通常由 mypopup 函数的 4 个输入参数排序,但不能使用 lapply 调用来完成,如下例仅恰好有 1 个输入参数:

  lapply(plot.list, function(x){  
    o <- observeEvent(event_data("plotly_click", source = paste("plotlyplot", x, sep = '.')), {
      print('clicked')
      if(values[[paste("particle_viewer", x, sep = "_")]]) {
        ## when click in plot: Highlight the clicked particle with java, but also store the clicked point
        values[[paste("HLval", x, sep = "_")]] <- event_data("plotly_click", source = paste("plotlyplot", x, sep = '.'))  ## this code stores the last clicked point so that the point stays active when object is re-rendered
      }
    })
  })

每次数据更改时都会调用销毁。

  observeEvent( values$TrainDFLogged,   {
    lapply(c("o"), function(x) {
          if (exists(x))
          {get(x)$destroy
            print('destroyed2')
          }
        })
  mypopup(values$TrainDFLogged, "SecondFile", "default", values$TrainPulses)
  })

更新 2

然而,当在 mypopup 函数代码之外创建观察者时,似乎不需要销毁并分配给 'o',点击只会按我刚刚发现的时间观察。所以也许我们应该简单地找到一种方法来在 lapplymapply 样式的解决方案中创建所有观察者,但在 mypopup 代码之外?

原因是在动态方法中创建了相同 observeEvent 的副本(lapply 超过 x 长度)

问题是 Shiny 在重建时覆盖 ui 元素(或者至少只显示它的最新版本,但是当你构建编号 observeEvents 来听一组带编号的按钮或类似按钮,如果您简单地从 1:10 中的 lapply.

构建它们,它会创建每个观察者的副本

防止这个问题的解决方案是,记录你到目前为止做了多少observers(最大nr循环),然后当与循环相关的代码更新时,需要更大的nr observers 的,只为高于先前最大值的 nrs 制作新的。

换句话说,遍历 'previous maximum'+1(第一次为 0)直到新的最大值,确保只有