R Shiny,如何在observeEvent调用中更新变量

时间:2017-08-03 06:19:13

标签: r shiny reactive-programming

我无法在observeEvent调用中更新列表。

该列表称为Participants,是列表列表 - 即每个用户的配置文件。任何用户都应在某个Participants电话上更新observeEvent

我已尝试使变量具有反应性且非反应性,但它​​不起作用。

以下是最低工作示例

ui.R

用户代码

library(shiny)

shinyUI( fluidPage(
    sidebarLayout(
        #---------------------------------------------------
        # accept user transid
        sidebarPanel(
            numericInput("transid", "Transid", 0), 
            actionButton("accept", "Accept" )
        ),
        #---------------------------------------------------
        # Return user spreadsheet
        mainPanel( verbatimTextOutput("userSpreadSheet"))
))
)

server.R

服务器的代码     #------------------------------------------------- -     ##################     #definition     库(有光泽)

## Create Participant List
ParticipantsDF <- data.frame(
    Name=stringi::stri_rand_strings(n=20, length=8, pattern="[a-z]"),
    ID=paste0("JA",1:20) ) 
spreadsheet  <- list(data.frame(foo=1:10, bar=runif(10), transid=NA) )
Participants <- apply( ParticipantsDF, 1, function(e){
     c( as.list(e), spreadsheet=spreadsheet ) })
ParticipantIDs <- ParticipantsDF$ID
ParticipantNames <- ParticipantsDF$Name

## Update Participants by changing a person
## based on user input of transid value
    ## change persons sublist named ``transid''
update_person <- function(transid, pid, participants){
    ## Which User
    userProfile_u <- participants[[pid]]
    ## Update User next transid to TRUE
    rows_vacant <- is.na(userProfile_u$spreadsheet$transid)
    row_update <- head( which(rows_vacant),1)
    userProfile_u$spreadsheet[row_update, "transid"] <- TRUE 
    ## Update Participants
    participants[[pid]] <- userProfile_u
    Participants <<- participants
}

#----------------------------------------------------------------------
##################
# Server 
server <- function( input, output, session){

    #---------------------------------------------------
    # Get authorized user: requires shiny-server-pro
    user <- session$user

    #---------------------------------------------------
    # Return user profile
    userPID <- which(ParticipantIDs == session$user )
    userProfile <- Participants[[userPID]]
    #---------------------------------------------------
    # When user clicks ``accept'', update Participants
    observeEvent(input$accept, {
        update_person(
            input$transid,
            userPID,
            Participants
        )
    })
    #---------------------------------------------------
    # Display spreadsheet to user
    ## Does Not Update!
    output$userSpreadSheet <- renderPrint({
        Participants[[userPID]][["spreadsheet"]] })
    ## Updates (Based on Accepted Answer)
    #ReactiveParticipants <- reactiveValues(Participants=Participants)
    #output$userSpreadSheet <- renderPrint({
    #    ReactiveParticipants$Participants[[userPID]][["spreadsheet"]]
    #})
    #observe({  invalidateLater(100)
    #    ReactiveParticipants$Participants <<- Participants
    #})
}
shinyServer(server)

如果我编辑上面的代码不使用renderPrint reactiveValues,那么它仍然无效。

1 个答案:

答案 0 :(得分:0)

看起来反应可能存在一些问题。据我所知,session$user在应用程序运行时(对于该用户)不会改变,因此反应语句及其依赖关系可能根本不会执行第二次(这就是为什么最后一个部分不会更新)

第二部分我不确定isolate如何在Participants上工作,因为这是全局环境中的静态变量,而不是反应对象。您是否可以提供完全可重现的代码?

编辑: 您的示例实际上非常接近,主要问题是您尝试在观察者(renderPrint)中读取静态全局变量。由于您的函数update_person在将参与者保存到全局环境时也返回参与者,您可以直接将其用作reactiveValue然后调用它:

server <- function(input, output, session){
  #---------------------------------------------------
  # Get authorized user: requires shiny-server-pro
  user <- session$user

  #---------------------------------------------------
  # Return user profile
  userPID <- which(ParticipantIDs == user )
  userProfile <- Participants[[userPID]]

  rv <- reactiveValues(Participants = Participants)

  observeEvent(input$accept, {
     rv$Participants <- update_person(
       input$transid,
       userPID,
       Participants
     )
  })

  output$userSpreadSheet <- renderPrint({
    rv$Participants[[userPID]][["spreadsheet"]]
  })
}

我希望它有所帮助。