由函数

时间:2018-02-28 13:32:54

标签: r shiny observers r-plotly

如何在数据发生变化时多次停止在函数内创建的观察者?

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

我制作了一个应用程序,在我的程序中需要几个(10个)版本的绘图,因此我编写了2个函数:

    创建地块的
  • myplotly
  • mypopup创建包含属于myplotly图中每个粒子的pulsehape图的弹出窗口,以及modaldialog弹出窗口中的选项按钮和所属观察者

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

此函数的缩短版本如下所示:

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)

}

pic

在创建或加载相应的数据帧时调用函数 * 1 ,并在数据更改时再次调用它们。

我面临的问题是,在数据发生变化并且用户点击一个点后,弹出窗口和所有观察者都会触发两次。如果再次更改数据,则弹出窗口会激活3次,依此类推。 除了基于旧数据的弹出窗口不了解图中现在有多个集群,因此如果单击集群2或3,则错误/ NA绘图等。

enter image description here

语句

  • 使用 obs $ destroy 可以解决问题,但不容易(参见脚注 * 2
  • 为什么我们首先要获得双重观察者?修复症状是一回事,理解为什么它们不是简单地被覆盖对我来说仍然是一个谜。

我创建了一个工作代码的精简示例以及一些运行它的文件,所有这些都可以在以下github链接上找到: https://github.com/madmark81/Observer-Madness

脚注

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

2 Maximilian提出了将观察者分配给变量的想法。但是这个的实现必须在mypopup函数之外完成,而且我还没有能够让它在使用多于1个输入参数的观察者上工作,这些参数通常由4个输入参数进行排序。 mypopup函数,但无法使用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
      }
    })
  })

每次更改数据时都会进行destroy调用。

  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函数代码的外部创建观察者时,不需要销毁并分配给&#39; o&#39;看来,只是按时发现点击次数。那么也许我们应该找到一种方法来创建lapplymapply样式解决方案中的所有观察者,但是在mypopup代码之外?

1 个答案:

答案 0 :(得分:0)

原因是使用动态方法(在{x1长度上,observeEvent)创建了同一lapply的副本

问题是Shiny会在重建ui元素时覆盖(或至少仅显示它的最新版本,但是当您构建编号的observeEvents来收听一组元素时会覆盖它们)编号按钮或类似的按钮,如果您只是从lapply中的1:10进行构建,则会创建每个观察者的副本。

防止出现此问题的解决方案是,记录到目前为止您已经制作了多少observers(最大循环nr次),然后记录与循环关联的代码的更新时间,并要求{ {1}},仅为高于先前最大值的nrs设置新的。

换句话说,将“上一个最大值” +1(第一次为0)循环到新的最大值,确保只有