在 observeEvent 中更新输入并更改 ui

Update input and change ui within observeEvent

我正在尝试让以下内容在 Shiny App 中运行:

  1. 有两个页面,每个页面由不同的 UI
  2. 定义
  3. 显示的第一个页面有一个带有一些默认文本的文本输入(即 textInput("text", "Text Input", "word")
  4. 当用户单击按钮时:(1) input$text 的值通过 updateTextInput 更新,(2) 页面切换。

第三部分不适合我。我已经定义了一个 actionButton,当它被点击时,我有两个被触发的 observeEvents:第一个带有 updateTextInput,第二个更新页面。问题是 input$text 没有被更新——似乎 updateTextInput 被忽略了。

当我注释掉切换 ui 的 observeEvent 时,updateTextInput 按预期工作。

知道如何让按钮既更新文本又切换 UI 吗?这是我正在制作的更大应用程序的一部分,但下面的示例重现了这个问题。

# UIs --------------------------------------------------------------------------
ui = (htmlOutput("page"))

ui_page1 = fluidPage(
  h1("Page 1"),
  actionButton("to_page2", "Go to Page 2"),
  textInput("text", "Text Input", "word")
)

ui_page2 <- fluidPage(
  h1("Page 2"),
  actionButton("to_page1", "Go to Page 1"),
  br(),
  h4("Displaying input$text - I want this show `new word`"),
  textOutput("input_text")
)

# Server -----------------------------------------------------------------------
server = function(input, output, session) {
  
  #### By default, start with page 1
  output$page <- renderUI({
    div(ui_page1)
  })
  
  #### To page 2
  observeEvent(input$to_page2, {
    updateTextInput(session, "text", value = "new word")
  }, priority = 3)
  
  # *** Comment this observeEvent out, and the updateTextInput works as expected
  observeEvent(input$to_page2, {

    output$page <- renderUI({
      div(ui_page2)
    })

  }, priority = 2)
  
  # To display the input$text value
  observeEvent(input$to_page2, {
    
    output$input_text <- renderText(input$text)
    
  }, priority = 1)
  
  #### To page 1
  observeEvent(input$to_page1, {
    
    output$page <- renderUI({
      div(ui_page1)
    })
    
  })
  
}

# shinyApp ---------------------------------------------------------------------
shinyApp(ui, server)

我不想给出类似“这行得通,但我不知道为什么”这样的答案,但是...

这行得通,我不知道为什么。

我更改了您的服务器功能,以便在 reactiveValues 对象中加注第 2 页上显示的单词。没有其他变化。

server = function(input, output, session) {
  v <- reactiveValues(
    word="word"
  )
  #### By default, start with page 1
  output$page <- renderUI({
    div(ui_page1)
  })
  observeEvent(input$input_word, {
    v$word <- input$input_word
  })
    #### To page 2
  observeEvent(input$to_page2, {
    v$word <- "new word"
    updateTextInput(session, "text", value = v$word)
  }, priority = 100)
  # *** Comment this observeEvent out, and the updateTextInput works as expected
  observeEvent(input$to_page2, {
    output$page <- renderUI({
      div(ui_page2)
    })
  }, priority = 200)
  # To display the input$text value
  observeEvent(input$to_page2, {
    output$input_text <- renderText(v$word)
  }, priority = 200)

  #### To page 1
  observeEvent(input$to_page1, {
    output$page <- renderUI({
      div(ui_page1)
    })
  })
}

但是在将其粘贴到此处时,我注意到您已经在观察者中定义了 output 对象。这绝不是一个好主意。我会看看这是不是根本原因...

更新

此服务器功能是否为您提供了您想要的行为?如果是这样,您的问题是因为您在 observers...

中定义了 output 对象
server = function(input, output, session) {
  renderPageUI <- function(id) {
    if (id == 1) ui_page1
    else ui_page2
  }
  #### By default, start with page 1
  output$page <- renderUI({
   renderPageUI(1)
  })
  #### To page 2
  observeEvent(input$to_page2, {
    updateTextInput(session, "text", value = "new word")
    renderPageUI(2)
  })
  #### To page 1
  observeEvent(input$to_page1, {
    renderPageUI(1)
  })
}

顺便说一句,每当我编写这种动态 UI 时,我总是最终将每个动态组件定义为一个模块,即使我知道组件只会有一个实例。它使跟踪 inputoutput id 属于哪个页面变得容易得多 - 因为它们对其他所有组件都是不可见的,除非我选择使它们可见。