Як прослуховувати більше одного виразу події в обробнику Shiny eventReactive


85

Я хочу, щоб дві різні події викликали оновлення даних, які використовуються різними графіками / виходами в моєму додатку. Один - це кнопка, по якій натискається ( input$spec_button), а інша - точка на крапці, яку натискають ( mainplot.click$click).

В основному, я хочу перерахувати для обох одночасно, але я не впевнений, як написати код. Ось що я маю зараз:

на сервері.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 (ввести $ spec_button)?
Гопала

Відповіді:


94

Я знаю, що це старе, але у мене було те саме питання. Я нарешті зрозумів це. Ви включаєте вираз у фігурні дужки та просто перераховуєте події / реактивні об’єкти. Моє (необґрунтоване) припущення полягає в тому, що Shiny просто виконує той самий аналіз реактивного покажчика для цього блоку виразів, що і для стандартного reactiveблоку.

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

РЕДАГУВАТИ

Оновлено для обробки випадку, коли останній рядок у виразі повертає NULL. Просто поверніть постійне значення.


1
Зміна прийнятої відповіді на цю, оскільки вона видається кращим рішенням, ніж моє оригінальне рішення.
Хілларі Сандерс

3
Чи можете ви визначити, яка подія була ініційована?
Пітер Вермонт,

Не те, що я знаю. Я робив це в декількох випадках, відстежуючи їх за окремими змінними та проводячи порівняння сам, щоб побачити, що змінилося. Але це негарно. Можливо, краще помістити основний код у функцію, а потім мати два спостереження за подіями, які викликають fn, а потім виконувати певні дії для кожної події.
Дункан Браун

8
Просто попередження: observeEventвикористовує ignoreNULL = TRUEза замовчуванням, що означає, що якщо mainplot.click$click(повертається значення) NULL, обробник ніколи не буде викликаний, навіть якщо його input$spec_buttonзмінити. Я б порадив щось на зразок відповіді @ JustAnother, щоб не допустити потрапляння в цю пастку.
greg L

1
Ще одне попередження: під час мого тестування я виявив, що цей синтаксис дужок ( {}) ПОТРІБУЄ, щоб кожна подія була у власному новому рядку, інакше вона не працює із помилкою "Помилка при розборі ...", як тільки синтаксичний аналізатор зустріне другу подію. наприклад, все в одному рядку: observeEvent({input$spec_button mainplot.click$click}, {...})не вдається. Відповідь @ JustAnother із використанням синтаксису S3 Generic comb ( c()) працює незалежно від нових рядків.
Брайан Д.

54

Також:

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

6
Хоча це схоже на відповідь @DuncanBrown, я виявив ситуацію, коли дві кнопки дії одночасно запускають модальний режим, це спрацювало, а {версія не працювала. Я не можу пояснити, чому це так.
Джон Павло

2
Додав коментар до відповіді @Duncan Brown про те, як ця відповідь відрізняється (і краще IMO)
greg L

Це не працює для мене - я отримую помилку (блискуча 1.0.5)
potockan

чи є спосіб дізнатись, яка подія була ініційована? скажімо, у мене є дві кнопки, input$button1і input$button2це робить дуже схожі речі, лише з іншим індексом. Я хотів би уникати копіювати код кілька разів лише тому, що не знаю індексу. Дякую!
Нікос Боссе

10

Я вирішив цю проблему, створивши реактивний об'єкт і використовуючи його у виразі змін подій. Як зазначено нижче:

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

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

4
Це дуже хороша відповідь, яка може отримати користь від додаткових пояснень. Хоча прийнята відповідь є більш простою, що робить її кращою для елементарних програм, ця відповідь більше підходить для великих та складних кодів. У відповіді відсутні два пункти (1) Вставлення (або перелік) ставить дві події в один рядок, роблячи код більш компактним. (2) Реактивний об'єкт економить зусилля повторювати однакові дві події знову і знову, якщо більше одного слухача слухає один і той же набір подій.
Агроном

5

Ось рішення, яке я придумав: в основному, створити порожній 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)  
  })

3
list(mainplot.click$click, input$spec_button)також буде працювати на шлях ОП.
Джон

1

Це все ще можна зробити за допомогою eventReactive, просто помістивши свої дії у вектор.

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

0

Ідея тут полягає в тому, щоб створити реактивну функцію, яка буде виконувати умову, яку ви хочете передати в obserEvent, а потім ви можете передати цю реактивну функцію, щоб перевірити правильність твердження. Наприклад:

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

Продовжуйте кодувати!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.