0

データが変更されたときに、関数内で作成されたオブザーバーが複数回存在しないようにする方法は?

更新: - テストを容易にするために、github のアプリをさらに簡素化しました。- 使用しようとしているdestroy ----

プログラム全体でいくつかの (10 程度の) プロットのバージョンを必要とするアプリを作成したため、2 つの関数を作成しました。

  • myplotlyプロットを作成する
  • mypopupプロット内の各粒子に属する pulseshape プロット、ポップアップmyplotly内のオプション ボタン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)

}

写真

関数*1は、対応するデータ フレームが作成またはロードされたときに呼び出され、データが変更されたときに再度呼び出されます。

私が直面している問題は、データが変更され、ユーザーがポイントをクリックした後、ポップアップとすべてのオブザーバーが 2 回起動することです。データが再度変更されると、ポップアップが 3 回発生します。また、古いデータに基づくポップアップは、プロットに複数のクラスターがあることを認識しないため、クラスター 2 または 3 をクリックすると、エラー/NA プロットなど..

ここに画像の説明を入力

ステートメント:

  • obs$destroyを使用すると問題が解決する可能性がありますが、簡単ではありません (脚注*2を参照)
  • そもそもなぜ私たちはダブルオブザーバーを得るのですか? 症状を修正することは 1 つのことですが、単純に上書きされない理由を理解することは、私にとってまだ謎です。

作業コードとそれを実行するためのいくつかのファイルの簡略化された例を作成しました。これらはすべて、次の github リンクにあります: https://github.com/madmark81/Observer-Madness

脚注

1関数として記述した理由は、ベース データフレームとパルス データフレームの一意の組み合わせ、およびグループ ID を含む列に応じて、このプロットとポップアップの組み合わせをメイン アプリで何度か適用するためです。そしてグループ名。

2 Maximilian は、変数へのオブザーバーの割り当てを使用するというアイデアを思いつきました。しかし、これの実装は mypopup 関数の外で行う必要があり、通常は mypopup 関数の 4 つの入力引数によって分類される複数の入力引数を使用するオブザーバーで動作させることができませんでした。ただし、たまたま入力引数が 1 つしかない次の例のように、lapply 呼び出しを使用して実行することはできません。

  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 関数コードの外側で作成される場合、破棄して「o」に割り当てる必要はないようです。クリックは、私が見つけた時間にのみ観察されます。したがって、すべてのオブザーバーをlapplyorスタイル ソリューションで作成する方法を単純に見つける必要がありますが、コードmapplyの外側にあるのでしょうか?mypopup

4

1 に答える 1