I am unable to update a list within an observeEvent call.
The list is called Participants
and is a list-of-lists - ie a profile for each user. Participants
is supposed to be updated by any user on a certain observeEvent
call.
I have tried making the variable reactive and also non-reactive, but it does not work.
Below is a minimum working example
The code for user
library(shiny)
shinyUI( fluidPage(
sidebarLayout(
#---------------------------------------------------
# accept user transid
sidebarPanel(
numericInput("transid", "Transid", 0),
actionButton("accept", "Accept" )
),
#---------------------------------------------------
# Return user spreadsheet
mainPanel( verbatimTextOutput("userSpreadSheet"))
))
)
The code for server #--------------------------------------------------- ################## # Definitions library(shiny)
## 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)
If I edit the above code not to use renderPrint reactiveValues, then it still does not work.
It looks that there might be some issues with reactivity. As far as I know, session$user
will not change during the application runtime (for that user) so the reactive statement and its dependencies might not execute the second time at all (that would be why the last piece does not update).
The second part I am not sure is how isolate
can work on Participants
as this is a static variable in global environment, not a reactive object. Can you perhaps provide a fully reproducible piece of code?
Edit: Your example is actually very close, the main problem is that you are trying to read static global variable in an observer ( renderPrint
). As your function update_person
also returns Participants while saving them to the global environment, you can use it directly as a reactiveValue and then call it:
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"]]
})
}
I hope it helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.