So warten Sie auf mehr als einen Ereignisausdruck in einem Shiny eventReactive-Handler


85

Ich möchte, dass zwei verschiedene Ereignisse eine Aktualisierung der Daten auslösen, die von verschiedenen Plots / Ausgaben in meiner App verwendet werden. Eine ist eine Schaltfläche, auf die geklickt wird ( input$spec_button), und die andere ist ein Punkt auf einem Punkt, auf den geklickt wird ( mainplot.click$click).

Grundsätzlich möchte ich für beide gleichzeitig aufgelistet sein, bin mir aber nicht sicher, wie ich den Code schreiben soll. Folgendes habe ich jetzt:

in 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
    }
  })

Die if-else-Klausel funktioniert jedoch nicht

Error in mainplot.click$click | input$spec_button : operations are possible only for numeric, logical or complex types

-> Gibt es eine Art Action-Combiner-Funktion, die ich für die mainplot.click$click | input$spec_buttonKlausel verwenden kann?


Können Sie die Ausgabe von! Is.null (Eingabe $ spec_button) überprüfen?
Gopala

Antworten:


93

Ich weiß, dass das alt ist, aber ich hatte die gleiche Frage. Ich habe es endlich herausgefunden. Sie fügen einen Ausdruck in geschweifte Klammern ein und listen einfach die Ereignisse / reaktiven Objekte auf. Meine (unbegründete) Vermutung ist, dass Shiny einfach die gleiche reaktive Zeigeranalyse für diesen Ausdrucksblock durchführt wie für einen Standardblock reactive.

observeEvent({ 
  input$spec_button
  mainplot.click$click
  1
}, { ... } )

BEARBEITEN

Aktualisiert, um den Fall zu behandeln, in dem die letzte Zeile im Ausdruck NULL zurückgibt. Geben Sie einfach einen konstanten Wert zurück.


1
Akzeptierte Antwort auf diese zu ändern, da es eine bessere Lösung zu sein scheint als meine ursprüngliche Lösung.
Hillary Sanders

3
Können Sie feststellen, welches Ereignis ausgelöst wurde?
PeterVermont

Nicht dass ich wüsste. Ich habe dies in einigen Fällen getan, indem ich sie in separaten Variablen verfolgt und den Vergleich selbst durchgeführt habe, um festzustellen, welche sich geändert haben. Aber es ist hässlich. Wahrscheinlich ist es besser, den Hauptcode in eine Funktion einzufügen, dann zwei ObservEvents zu haben, die das fn aufrufen und dann für jedes Ereignis bestimmte Dinge tun.
Duncan Brown

8
Nur eine Warnung: observeEventAnwendungen ignoreNULL = TRUEstandardmäßig die Mittel , wenn mainplot.click$click(der Rückgabewert) ist NULL, wird der Handler nie auch aufgerufen werden , wenn input$spec_buttongeändert. Ich würde so etwas wie die Antwort von @ JustAnother empfehlen, um zu verhindern, dass Sie in diese Falle tappen.
Greg L

1
Eine weitere Warnung: Bei meinen Tests habe ich festgestellt, dass diese Klammer-Syntax ( {}) jedes Ereignis in einer eigenen neuen Zeile benötigt, andernfalls schlägt sie mit "Fehler beim Parsen ..." fehl, sobald der Parser auf das zweite Ereignis stößt. zB alles in einer Zeile: observeEvent({input$spec_button mainplot.click$click}, {...})schlägt fehl. Die Antwort von @ JustAnother mit S3 Generic Combine Syntax ( c()) funktioniert unabhängig von Zeilenumbrüchen.
Brian D

53

Ebenfalls:

observeEvent(c( 
  input$spec_button,
  mainplot.click$click
), { ... } )

6
Obwohl dies der Antwort von @DuncanBrown sehr ähnlich sieht, habe ich eine Situation gefunden, in der 2 Aktionstasten beide ein Modal auslösen. Dies hat funktioniert und die {Version nicht. Ich kann nicht erklären, warum das so ist.
John Paul

2
Fügte einen Kommentar zu @Duncan Browns Antwort hinzu, wie diese Antwort anders ist (und besser IMO)
Greg L

Dieser funktioniert nicht für mich - ich bekomme einen Fehler (glänzend 1.0.5)
Potockan

10

Ich habe dieses Problem gelöst, indem ich ein reaktives Objekt erstellt und es im Ereignisänderungsausdruck verwendet habe. Wie nachstehend:

xxchange <- reactive({
paste(input$filter , input$term)
})

output$mypotput <- eventReactive( xxchange(), {
...
...
...
} )

4
Dies ist eine sehr gute Antwort, die von mehr Erklärungen profitieren könnte. Während die akzeptierte Antwort einfacher ist, was sie für rudimentäre Programme besser macht, ist diese Antwort besser für große und komplexe Codes geeignet. In der Antwort scheinen zwei Punkte zu fehlen. (1) Durch Einfügen (oder Liste) werden die beiden Ereignisse in dieselbe Zeile eingefügt, wodurch der Code kompakter wird. (2) Das reaktive Objekt erspart den Aufwand, dieselben zwei Ereignisse immer wieder zu wiederholen, wenn mehr als ein Zuhörer auf denselben Satz von Ereignissen wartet.
Landwirt

5

Hier ist die Lösung, die ich gefunden habe: Erstellen Sie im Grunde genommen einen leeren reactiveValuesDatenhalter und ändern Sie seine Werte basierend auf zwei separaten observeEventInstanzen.

  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)  
  })

3
wird list(mainplot.click$click, input$spec_button)auch für OP funktionieren.
John

0

Dies kann mit eventReactive weiterhin durchgeführt werden, indem Sie Ihre Aktionen einfach in einen Vektor einfügen.

eventReactive(
  c(input$spec_button, mainplot.click$click), 
{ ... } )

0

Hier geht es darum, eine reaktive Funktion zu erstellen, die die Bedingung ausführt, die Sie in watchEvent übergeben möchten. Anschließend können Sie diese reaktive Funktion übergeben, um die Gültigkeit der Anweisung zu überprüfen. Zum Beispiel:

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(), 
    { ... } 
)

Codieren Sie weiter!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.