RShiny shinyalert 回调不更新变量?

RShiny shinyalert callback not updating variables?

在过去的几周里,我一直在尝试使用 shinyalert() 来探索在警报中使用输入并在输入未留空时触发链式 shinyalert() 的潜力。在我看来,有几件事是高度优先的:

1:如果选择了取消按钮,我需要取消链式模​​态。我相信我已经弄清楚了这一部分。

2:如果shinyalert中的任何输入留空,我也需要取消链式模​​态。

下面的代码 似乎 在第一次使用时可以运行,但很快就会发现它在内存中保存了变量(不确定这是否是正确的术语)出于某种我不能的原因算出:

library(shiny)
library(shinyalert)

ui <- fluidPage(
  useShinyalert(),
  actionButton("run", "Run", class = "btn-success")
)
server <- function(input, output, session) {
  
  functest = function(num) {
    ans = is.na(num)
    list(ans = ans)
  }
  
  observeEvent(input$run,
               shinyalert(
                 title = "What is your name?",
                 html = T,
                 text = tagList(textInput("name", "What's your name?", "Jack"),
                                numericInput("num", "Number Here", value = NA)),
                 callbackR = function(x) { 
                   if(x != FALSE & !is.na(input$num)) {
                     shinyalert(html = T,
                                text = tagList(
                                  div(paste(input$name, "'s favorite color is Black", sep = "")),
                                  div(paste("Is input$num NA? ", functest(input$num)$ans, sep = ""))
                                ),
                                showCancelButton = T,
                     )
                   }
                   else {
                     closeAlert()
                   }
                 },
                 closeOnEsc = T,
                 showConfirmButton = TRUE,
                 closeOnClickOutside = T,
                 showCancelButton = TRUE,
               )
  )
}
shinyApp(ui = ui, server = server)

如果点击取消按钮,链式模式将不会按预期显示。看起来,即使 num 输入留空并按下确认按钮,链式模式也不会显示(耶!)。然而,当输入一个数字时,奇怪的事情发生在初始 运行:

之后

如果我将名称更改为 'Todd' 并输入一个数字,链式模式将按预期显示。但是,一旦再次 运行 并保留默认名称 'Jack' 且未输入任何数字,它仍将调用链式模态并显示前一个 运行 的输出,这样它仍然说 Todd 并且它会说 num 输入不是 NA 而不是说 'Jack' 并且 num 输入是 NA。谁能帮忙解释一下为什么会这样?

让我更加困惑的是,似乎回调中的任何内容都无法通过典型的闪亮命名法直接访问。下面是一个示例,其中链式模态和原始模态都具有完全相同的 uiOutput 调用。初始模态中的 uiOutput 有效,而链式模态中的 uiOutput 无效。

library(shiny)
library(shinyalert)

ui <- fluidPage(
  useShinyalert(),
  actionButton("run", "Run", class = "btn-success")
)
server <- function(input, output, session) {
  observeEvent(input$run,
               shinyalert(
                 title = "What is your name?",
                 html = T,
                 text = tagList(textInput("name", "What's your name?", "Dean"), 
                                div(uiOutput("test"))),
                 callbackR = function(x) { if(x != FALSE) shinyalert(html = T,
                                                                     text = tagList(
                                                                       div(uiOutput("test")))
                                                                     )
                                                                     },
                 closeOnEsc = T,
                 showConfirmButton = TRUE,
                 closeOnClickOutside = T,
                 showCancelButton = TRUE,
               )
               )
  
  output$test = renderUI({
    paste(input$name, "'s favorite color is black", sep = "")
  })
}
shinyApp(ui = ui, server = server)

这就是第一段代码中functest()函数的原因。如果我将输入传递给函数,似乎可以显示它。但是由于某些原因,使用 renderUI() 或类似的东西不起作用。我不禁觉得这两个问题是相关的...

无论如何,我确信我感到困惑的是一些基本的东西,但我真的很感激任何人可以提供的任何意见。我真的更喜欢使用 shinyalert() 来确保我一直在构建的应用程序的一致性,但如果可以通过默认模式完成类似的事情,那也可以。

感谢阅读!

非常感谢 Stéphane Laurent for commenting the existing bug thread, I never would've found that! Evidently my issues are just a bug with shinyalert() and can be fixed by delaying evaluation for ~380 ms. It seems Dave is pretty busy so I'm not sure if/when it will get fixed but if you are encountering similar issues in the future, I'd recommend checking https://github.com/daattali/shinyalert/issues/46 以防此解决方法不再需要。

可以使用 shinyjs 库中的 delay() 来做到这一点。虽然不是理想的长期解决方案,但它完美地解决了我的疑虑。它不仅允许我使用典型的闪亮命名法(在回调中使用 uiOutput),而且还解决了我在闪亮保留旧值时遇到的问题。下面是调整后的第一组代码的示例(第二组非常相似):

library(shiny)
library(shinyalert)
library(shinyjs)

ui <- fluidPage(
  useShinyalert(),
  useShinyjs(),
  actionButton("run", "Run", class = "btn-success")
)

server <- function(input, output, session) {
  
  observeEvent(input$run,
               shinyalert(
                 title = "What is your name?",
                 html = T,
                 text = tagList(textInput("name", "What's your name?", "Jack"),
                                numericInput("num", "Number Here", value = NA)),
                 callbackR = function(x) { 
                   if(x != FALSE & !is.na(input$num)) {
                     delay(400,
                           shinyalert(html = T,
                                      text = tagList(
                                        div(uiOutput("text")),
                                        div(uiOutput("isna"))
                                      )
                           )
                     )
                   }
                     else {
                       closeAlert()
                     }
                 },
                 closeOnEsc = T,
                 showConfirmButton = TRUE,
                 closeOnClickOutside = T
               )
  )
  
  output$text = renderUI({
    paste(input$name, "'s favorite color is black", sep = "")
  })
  
  output$isna = renderUI({
    paste("Is input$num NA? ", is.na(input$num), sep = "")
  })
}

shinyApp(ui = ui, server = server)

再次感谢,希望对大家有所帮助!