R Shiny, отслеживает переменную и обновляет пользовательский интерфейс

Я пытаюсь создать систему сообщений в блестящем приложении, которое будет получать уведомления при выполнении определенных задач, но в настоящее время это не работает:

UI:

library(shinydashboard)
dashboardPage(
  dashboardHeader(title = "My Dashboard",
                  dropdownMenuOutput("messageMenu")
),
dashboardSidebar(),
dashboardBody("Hi", actionButton("go", label="DO STUFF!"), actionButton("go2", label="DO MORE STUFF!"))
)

Сервер:

library(shinydashboard)

shinyServer(function(input, output) {

  M_Store <- reactiveValues(DF = data.frame(
    from = c("Admininstrator", "New User", "Support"),
    message = c(
      "Sales are steady this month.",
      "How do I register?",
      "The new server is ready."
    ),
    stringsAsFactors = FALSE
  ))

  output$messageMenu <- renderMenu({
    msgs <- apply(M_Store$DF, 1, function(row) {
      messageItem(from = row[["from"]], message = row[["message"]])
    })
    dropdownMenu(type = "messages", .list = msgs)
  })

  reactive({
    input$go
    message("Button pressed. Execute analysis!")
    message("Pretend analysis got done!")
    message("Now want to send a message that the analysis is done!")
    M_Store$DF <- rbind(isolate(M_Store$DF), data.frame(from="Meee", message="Done message!"))
    })

  reactive({
    input$go2
    message("Second button pressed. Execute second analysis!")
    message("Some computation!")
    message("Want to update the user on progress with a message!")
    M_Store$DF <- rbind(isolate(M_Store$DF), data.frame(from="Someone else!", message="Progress message2!"))
    message("More computations....")
    message("Done, want to tell user I'm done!")
    M_Store$DF <- rbind(isolate(M_Store$DF), data.frame(from="Someone else!", message="Done message2!"))
  })
})

Вы видите мое намерение? Я хотел бы иметь возможность отправлять сообщения об анализе или прогрессе в действиях. Я думал, что наличие реактивного DF в M_Store будет означать, когда им манипулируют, тогда все зависит от него, то есть вывод $ messageMenu.

То, что я хотел бы сделать, аналогично индикаторам выполнения shiny: когда вы выполняете свои вычисления, вы просто обновляете их переменные, и они меняются на экране.

Спасибо, Бен.


person Ward9250    schedule 11.12.2015    source источник


Ответы (1)


Вы можете использовать функцию reactiveValues в сочетании с isolate. Ваш случай будет выглядеть примерно так:

messageData <- data.frame(from = character(0),  message = character(0), stringsAsFactors = F) #simplified this a bit

shinyServer(function(input, output) {

  M_Store <- reactiveValues(DF = messageData)

  newMessage <- reactive(data.frame(from = as.character(input$from),message = as.character(input$message)))
  observe({
    M_Store$DF <- rbind(isolate(M_Store$DF), newMessage())
  })

  output$myUI <- renderUI({

   #some code
   ... M_Store$DF ...
   #some code

  })
})

M_Store$DF теперь является реактивным значением. При изменении input$from или input$message, newMessage изменится, что, в свою очередь, станет rbind новой строкой. Если M_Store находится внутри какой-либо renderUI функции, он обновит это значение как wll.

Если я получу то, что вы пытаетесь сделать, вы можете изменить newMessage на eventReactive, чтобы пользователю нужно было нажать кнопку, чтобы зафиксировать какие-либо изменения (вместо того, чтобы запускаться каждый раз, когда изменяется любой ввод).

РЕДАКТИРОВАТЬ:

Основываясь на вашем редактировании выше, вам нужно следующее вместо ваших реактивных функций:

observeEvent(input$go,{
    message("Button pressed. Execute analysis!")
    message("Pretend analysis got done!")
    message("Now want to send a message that the analysis is done!")
    M_Store$DF <- rbind(isolate(M_Store$DF), data.frame(from="Meee", message="Done message!"))
  })

Это срабатывает каждый раз, когда значение input$go изменяется (каждый раз, когда нажимается кнопка). Если вы поместите сюда другие входные или реактивные значения, вы можете привязать их к другим процессам или элементам пользовательского интерфейса.

person Chris    schedule 11.12.2015
comment
Я пытаюсь сделать так, чтобы, когда кто-то выполняет какое-либо действие, например загружает данные или выполняет некоторый анализ, после завершения действия сообщение будет отправлено в messageData и отображено в пользовательском интерфейсе. Конкретное сообщение будет сгенерировано, когда определенное реактивное выражение, например. t-тест, который полагается на входные данные, завершается. - person Ward9250; 11.12.2015
comment
Я только что отредактировал вопрос, чтобы показать на игрушечном примере, что именно я хочу делать. (Но не работает) - person Ward9250; 11.12.2015