问题:updateSelectizeInput
中的 observeEvent
调用会更改浏览器中显示的值,但不会更改我可以使用 input$
< 从代码访问的值/p>
背景:在我的 Shiny 应用中,我希望输入具有以下属性:
我目前有一个 observeEvent
监视查询字符串,当它看到一个时,它调用 updateSelectizeInput
,但是,在它这样做之后,输入不变。
示例:
library(shiny)
possibleLetters = LETTERS[1:10]
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectizeInput(inputId='letters',
label='Your letters:',
choices=NULL,
selected=NULL,
multiple=T,
width='100%'),
actionButton("recompute",
"Recompute now")
),
mainPanel(
h3("Letters: "),
textOutput('lettersDisplay'),
h3("Indices of letters: "),
textOutput('lettersIndicesDisplay')
)
)
)
server <- function(input, output, session) {
updateSelectizeInput(inputId='letters',
choices=c('',possibleLetters),
server=T)
userLetters = eventReactive(input$recompute, ignoreNULL=FALSE, {
if (length(input$letters) == 0) {
return (possibleLetters)
} else (
return (input$letters)
)
})
userLetterIndices = reactive({
return(match(userLetters(),LETTERS))
})
queryStringObserver = observeEvent(session$clientData$url_search, {
query <- parseQueryString(session$clientData$url_search)
if (!is.null(query$letters)) {
cat(file=stderr(), paste0('observeEvent running - user specified param is: ',query$letters,'\n'))
updateSelectizeInput(session,
inputId="letters",
choices = possibleLetters,
selected = query$letters,
server=T)
cat(file=stderr(), paste0('observeEvent running - ran updateSelectizeInput, input$letters is now: ',input$letters,'\n'))
}
})
output$lettersDisplay = renderText({
return(paste(userLetters(),collapse=' '))
})
output$lettersIndicesDisplay = renderText({
return(paste(userLetterIndices(), collapse=' '))
})
}
shinyApp(ui = ui, server = server, options = list(port=1111))
重现问题的步骤:运行应用程序,然后导航到 http://localhost:1111/?letters=A
您会发现浏览器窗口的 selectize 字段中确实填充了“A”,但是,input
值尚未更新。在您的控制台中,您将看到:
observeEvent running - user specified param is: A
observeEvent running - ran updateSelectizeInput, input$letters is now:
这样,查询字符串已经被正确解析,updateSelectizeInput
已经被调用,但是当之后访问input$letters
时,它的值没有改变。
我怀疑这与我对反应图或其他东西的理解中的一些基本缺陷有关,但在仔细研究Mastering Shiny后,我仍然无法弄清楚为什么这个调用没有任何作用。
答案 0 :(得分:1)
input$letters
的值更新,只是在您尝试打印它时还没有更新。我不确定 Shiny 如何或是否批量处理消息,但您的 observeEvent
最终会触发一条消息发送到客户端以更新输入,然后必须通知服务器已更新。至少,我假设它会完成当前观察者代码的执行,但通过一些修补看起来 Shiny 可能会在向客户端发送消息之前执行所有必要的反应代码。
虽然 input$letters
的值不会使用您的给定代码打印任何内容,但如果我单击重新计算,它确实会按预期更新文本。基本上,这里或多或少是我认为与您的代码发生的对话:
Client: Yo, server. The user added a query parameter: letters=A.
Server: Hmmm, ok I will just run this observeEvent code. Oh, the developer wants to know the current value of `input$letters`. Client, can you help a server out with that input value.
Client: No problem, friend-o. The current selected value is NULL.
Server: Well, let me just cat this NULL to the stderr.
Server (~1 ms later): Yo, client. I finished running the observeEvent code and you should really update that selectize input. It would make everyone happy.
Client: Can do.
Client (~2 ms later): Whoa, the select input updated. I gots to tell server about this jawn. Hey server, input$letters just changed to `A`. Just FYI.
Server: Hmm, good to know. Nothing for me to do about that.
当服务器打印 inputletters
时,该值仍然为 NULL,因为它还没有告诉客户端更新它。实际上,我不确定服务器是否轮询客户端以获取该值,或者是否从它自己的当前值列表中查找它,但无论哪种方式,当它转到该值时它仍然没有更新。>
将您的 cat
语句移至单独的 observe
语句,上面的对话将更改为
Client (~2 ms later): Whoa, the select input updated. I gots to tell server about this jawn. Hey server, input$letters just changed to `A`. Just FYI.
Server: WHAT?!!! OMG! I MUST TELL STDERR ABOUT THIS!!
我认为您的代码本身实际上没有任何问题。抱歉,服务器和客户端的所有个性都发生了变化,但希望这会有所帮助。
答案 1 :(得分:0)
要实现应用程序的预期行为,立即使用给定的查询字符串显示结果(无需等待用户立即按重新计算),需要进行以下更改:
if(!input$recompute)
)update_qs
代码:
library(shiny)
possibleLetters = LETTERS[1:10]
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectizeInput(inputId='letters',
label='Your letters:',
choices=NULL,
selected=NULL,
multiple=T,
width='100%'),
actionButton("recompute",
"Recompute now")
),
mainPanel(
h3("Letters: "),
textOutput('lettersDisplay'),
h3("Indices of letters: "),
textOutput('lettersIndicesDisplay')
)
)
)
server <- function(input, output, session) {
userLetters = eventReactive(input$recompute, ignoreNULL=FALSE, {
query <- parseQueryString(session$clientData$url_search)
if (!input$recompute & !is.null(query$letters)) {
selectedLetters = strsplit(query$letters,';')[[1]]
} else if (is.null(input$letters)) {
selectedLetters = character(0)
} else (
selectedLetters = input$letters
)
updateSelectizeInput(session,
inputId="letters",
choices = c('',possibleLetters),
selected = selectedLetters,
server=T)
if (length(selectedLetters)==0) {
return (possibleLetters)
} else {
return (selectedLetters)
}
})
update_qs = observeEvent(input$recompute, {
if (!identical(userLetters(),possibleLetters)) {
new_qs = paste0('?letters=',paste0(userLetters(),collapse=';'))
} else {
new_qs = '?'
}
updateQueryString(new_qs, mode='push')
})
userLetterIndices = reactive({
return(match(userLetters(),LETTERS))
})
output$lettersDisplay = renderText({
return(paste(userLetters(),collapse=' '))
})
output$lettersIndicesDisplay = renderText({
return(paste(userLetterIndices(), collapse=' '))
})
}
# Run the application
shinyApp(ui = ui, server = server, options = list(port=1111))