【问题标题】:Trigger observeEvent in Shiny even when condition hasn't changed即使条件没有改变,也可以在 Shiny 中触发 observeEvent
【发布时间】:2020-01-16 16:35:06
【问题描述】:

由于observeEvent 的工作方式(通常非常直观),我在获取我正在寻找的应用程序中的功能时遇到了一些问题。

我正在寻找的基本功能是用户可以输入几个数字,单击“提交”,然后弹出一个模式以获取用户的姓名。之后,应用程序记录名称并对数字求和,然后清除输入。然后我希望用户能够使用相同的名称重复该过程 - 但应用程序当前的结构使得总和使用 observeEvent 仅在名称不同时响应(即,使用相同的名称两次一行不起作用,尽管我希望这样做)。您可以在应用程序中看到我的解决方案尝试是重置inputSweetAlert 的输入(使用shinyjs),但我认为它无法访问它,因为它实际上不在 UI 端。我正在使用 shinyWidgets sweetAlerts,我想继续这样做。

这是一个示例应用:

library("shiny")
library("shinyWidgets")
library("shinyjs")

ui <- fluidPage(
  shinyjs::useShinyjs(),
  numericInput("num1", "Enter a number", value=NULL),
  numericInput("num2", "Enter another number", value=NULL),
  actionButton(inputId = "go", label = "submit"),
  verbatimTextOutput(outputId = "res1"),
  verbatimTextOutput(outputId = "res2")
)

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

  observeEvent(input$go, {
    inputSweetAlert(session = session, inputId = "name", title = "What's your name?")
  })

  x <- reactiveValues(val=NULL)

  observeEvent(input$name, {
    x$val <- input$num1 + input$num2
    confirmSweetAlert(session = session, inputId = "confirmed", title = "Success!", text = "Your responses have been recorded. All is in order.", type = "success", btn_labels = c("Ok, let me continue")
    )
  })

  ## A possible approach to a solution...
  observeEvent(input$confirmed, {
    shinyjs::reset("num1") 
    shinyjs::reset("num2") 
    shinyjs::reset("name")
  })

  output$res1 <- renderPrint(paste("Name:", input$name))
  output$res2 <- renderPrint(paste("Sum:", x$val))
}

shinyApp(ui = ui, server = server)

感谢您提供的任何帮助!

【问题讨论】:

  • 您好,您使用的是哪个版本的shinyWidgets
  • @Victorp,我在 0.4.9。
  • 谢谢,它对我有用,很奇怪,当你第二次使用inputSweetAlert 时,值设置为NULL。尽管如此,我已经在上一个开发版 shinyWidgegts 中实施了@ismirsehregal 建议
  • 嗯...奇怪的是它现在也适用于我,尽管它以前显然没有这种行为。无论哪种方式,感谢您更明确地包含该行为!

标签: r shiny shinyjs shinywidgets


【解决方案1】:

你可以通过JS重置input$name

runjs('Shiny.setInputValue("name", null, {priority: "event"});')

这是一个工作示例:

library("shiny")
library("shinyWidgets")
library("shinyjs")

ui <- fluidPage(
  shinyjs::useShinyjs(),
  numericInput("num1", "Enter a number", value = NULL),
  numericInput("num2", "Enter another number", value = NULL),
  actionButton(inputId = "go", label = "submit"),
  verbatimTextOutput(outputId = "res1"),
  verbatimTextOutput(outputId = "res2")
)

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

  observeEvent(input$go, {
    inputSweetAlert(session = session, inputId = "name", title = "What's your name?")
    runjs('Shiny.setInputValue("name", null, {priority: "event"});')
  })

  x <- reactiveValues(val = NULL)

  observeEvent(input$name, {
    x$val <- input$num1 + input$num2
    confirmSweetAlert(session = session, inputId = "confirmed", title = "Success!", text = "Your responses have been recorded. All is in order.", type = "success", btn_labels = c("Ok, let me continue"))
  })

  observeEvent(input$confirmed, {
    shinyjs::reset("num1") 
    shinyjs::reset("num2") 
    shinyjs::reset("mytext")
  })

  output$res1 <- renderPrint(paste("Name:", input$name))
  output$res2 <- renderPrint(paste("Sum:", x$val))
}

shinyApp(ui = ui, server = server)

更多信息请查看article

【讨论】:

  • 这行得通(+1),但我不明白。有了这个解决方案,为什么input$name 不是renderPrint(paste("Name:", input$name)) 中的NULL
  • 点击提交按钮后是NULL
  • 我猜他们需要使用{priority: "event"}。另见this
  • 非常好的解决方案,感谢您提供的额外资源。我希望我早点知道!
  • 为子孙后代:当我模块化我的应用程序并不得不拆分 js 命令以命名 id 时,我像这样调整了您的解决方案,它继续出色地工作:@987654333 @
【解决方案2】:

这是一种解决方法。这个想法在于在每次点击按钮时更改输入 ID。

library("shiny")
library("shinyWidgets")
library("shinyjs")

ui <- fluidPage(
  shinyjs::useShinyjs(),
  numericInput("num1", "Enter a number", value=NULL),
  numericInput("num2", "Enter another number", value=NULL),
  actionButton(inputId = "go", label = "submit"),
  verbatimTextOutput(outputId = "res1"),
  verbatimTextOutput(outputId = "res2")
)

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

  go <- reactive({
    input$go
  })

  observeEvent(input$go, {
    inputSweetAlert(session = session, inputId = sprintf("name-%d", go()), 
                    title = "What's your name?")
  })

  x <- reactiveValues(val=NULL)

  observeEvent(input[[sprintf("name-%d", go())]], {
    x$val <- input$num1 + input$num2
    confirmSweetAlert(session = session, inputId = "confirmed", title = "Success!", text = "Your responses have been recorded. All is in order.", type = "success", btn_labels = c("Ok, let me continue")
    )
  })

  ## A possible approach to a solution...
  observeEvent(input$confirmed, {
    shinyjs::reset("num1") 
    shinyjs::reset("num2") 
    shinyjs::reset("mytext")
  })

  output$res1 <- renderPrint(paste("Name:", input[[sprintf("name-%d", go())]]))
  output$res2 <- renderPrint(paste("Sum:", x$val))
}

shinyApp(ui = ui, server = server)

【讨论】:

  • 也是可行的办法!
  • 感谢您的回复。一个很好的方法,但在我的实际用例中,我通过应用程序在其他几个地方引用了该输入,因此@ismirsehregal 的解决方案更简洁,并且需要的下游更改更少。
猜你喜欢
  • 2018-12-14
  • 2019-08-01
  • 1970-01-01
  • 2019-07-22
  • 2012-07-07
  • 2021-09-07
  • 2016-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多