Cách lắng nghe nhiều hơn một biểu thức sự kiện trong một sự kiện Shiny


85

Tôi muốn hai sự kiện khác nhau kích hoạt cập nhật dữ liệu đang được sử dụng bởi các lô / đầu ra khác nhau trong ứng dụng của tôi. Một là một nút đang được nhấp ( input$spec_button) và một là một điểm trên dấu chấm đang được nhấp ( mainplot.click$click).

Về cơ bản, tôi muốn liệt kê cho cả hai cùng một lúc, nhưng tôi không chắc chắn về cách viết mã. Đây là những gì tôi có bây giờ:

trong máy chủ.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
    }
  })

Nhưng mệnh đề if-else không hoạt động

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

-> Có loại hàm kết hợp hành động nào mà tôi có thể sử dụng cho mainplot.click$click | input$spec_buttonmệnh đề không?


Bạn có thể kiểm tra đầu ra của! Is.null (đầu vào $ spec_button) không?
Gopala

Câu trả lời:


94

Tôi biết điều này là cũ, nhưng tôi đã có cùng một câu hỏi. Cuối cùng tôi đã tìm nó ra. Bạn bao gồm một biểu thức trong dấu ngoặc nhọn và chỉ cần liệt kê các sự kiện / đối tượng phản ứng. Phỏng đoán (không có căn cứ) của tôi là sáng bóng chỉ đơn giản thực hiện cùng một phân tích con trỏ phản ứng đối với khối biểu thức này như đối với một reactivekhối tiêu chuẩn .

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

BIÊN TẬP

Đã cập nhật để xử lý trường hợp dòng cuối cùng trong biểu thức trả về NULL. Chỉ cần trả về một giá trị không đổi.


1
Thay đổi câu trả lời được chấp nhận cho câu trả lời này vì nó có vẻ là một giải pháp tốt hơn so với giải pháp ban đầu của tôi.
Hillary Sanders

3
Bạn có thể xác định sự kiện nào đã được kích hoạt không?
PeterVermont,

Không phải là tôi biết. Tôi đã thực hiện điều này trong một vài trường hợp bằng cách theo dõi chúng trong các biến riêng biệt và tự mình so sánh để xem cái nào đã thay đổi. Nhưng nó xấu xí. Có lẽ tốt hơn nên đặt mã chính trong một hàm, sau đó có hai ObserEvents gọi fn và sau đó thực hiện các nội dung cụ thể cho từng sự kiện.
Duncan Brown

8
Chỉ là một cảnh báo: observeEventsử dụng ignoreNULL = TRUEtheo mặc định, có nghĩa là nếu mainplot.click$click(giá trị trả về) là NULL, trình xử lý sẽ không bao giờ được gọi ngay cả khi input$spec_buttonthay đổi. Tôi muốn giới thiệu một cái gì đó giống như câu trả lời của @ JustA Another để tránh rơi vào cái bẫy này.
greg L

1
Một cảnh báo khác: trong thử nghiệm của tôi, tôi thấy rằng cú pháp ngoặc này ( {}) YÊU CẦU mỗi sự kiện phải ở trên dòng mới của chính nó, nếu không nó sẽ không thành công với "Lỗi trong phân tích cú pháp ..." ngay khi trình phân tích cú pháp gặp sự kiện thứ hai. ví dụ, tất cả trên một dòng: observeEvent({input$spec_button mainplot.click$click}, {...})không thành công. Câu trả lời của @ JustA Another sử dụng Cú pháp kết hợp chung của S3 ( c()) hoạt động bất kể dòng mới.
Brian D

54

Cũng thế:

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

6
Mặc dù điều này trông rất giống với câu trả lời của @DuncanBrown, tôi đã tìm thấy một tình huống trong đó cả 2 nút hành động đều kích hoạt một phương thức, điều này hoạt động và {phiên bản thì không. Tôi không thể giải thích tại sao lại như vậy.
John Paul

2
Đã thêm nhận xét vào câu trả lời của @Duncan Brown về việc câu trả lời này khác biệt như thế nào (và IMO tốt hơn)
greg L

Cái này không làm việc cho tôi - Tôi nhận được một lỗi (sáng bóng 1.0.5)
potockan

có cách nào để tìm ra sự kiện nào đã được kích hoạt không? giả sử tôi có hai nút input$button1input$button2làm những việc rất giống nhau, chỉ với một chỉ mục khác. Tôi muốn tránh sao chép mã nhiều lần chỉ vì tôi không biết chỉ mục. Cảm ơn!
Nikos Bosse

10

Tôi đã giải quyết vấn đề này bằng cách tạo một đối tượng phản ứng và sử dụng nó trong biểu thức thay đổi sự kiện. Như sau:

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

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

4
Đây là một câu trả lời rất tốt có thể được hưởng lợi từ việc giải thích nhiều hơn. Mặc dù câu trả lời được chấp nhận đơn giản hơn nên nó tốt hơn cho các chương trình thô sơ, câu trả lời này phù hợp hơn với các mã lớn và phức tạp. Hai điểm dường như bị thiếu trong câu trả lời (1) Dán (hoặc danh sách) đặt hai sự kiện trên cùng một dòng làm cho mã gọn gàng hơn. (2) Đối tượng phản ứng tiết kiệm nỗ lực lặp đi lặp lại hai sự kiện giống nhau nếu có nhiều người nghe đang nghe cùng một nhóm sự kiện.
Nông nghiệp

5

Đây là giải pháp mà tôi đã đưa ra: về cơ bản, tạo một reactiveValuesngười giữ dữ liệu trống , sau đó sửa đổi các giá trị của nó dựa trên hai observeEventtrường hợp riêng biệt .

  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)cũng sẽ hoạt động theo cách của OP.
John

1

Điều này vẫn có thể được thực hiện với eventReactive bằng cách chỉ cần đặt các hành động của bạn vào một vector.

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

0

Ý tưởng ở đây là tạo một hàm phản ứng sẽ thực thi điều kiện bạn muốn chuyển trong ObserEvent và sau đó bạn có thể chuyển hàm phản ứng này để kiểm tra tính hợp lệ của câu lệnh. Ví dụ:

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

Tiếp tục mã hóa!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.