首页 > 解决方案 > 在 observeEvent 中更新输入并更改 ui

问题描述

我试图让以下内容在闪亮的应用程序中工作:

  1. 有两个页面,每个页面由不同的 UI 定义
  2. 显示的第一页有一个带有一些默认文本的 textInput(即textInput("text", "Text Input", "word")
  3. 当用户单击按钮时:(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)

标签: rshinyshiny-reactivity

解决方案


我讨厌按照“这行得通,但我不知道为什么”这样的方式给出答案,但是......

这有效,我不知道为什么。

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

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在观察者中定义了对象。这绝不是一个好主意。我看看是不是这个问题的根源...

更新

此服务器功能是否为您提供了您想要的行为?如果是这样,您的问题是因为您在rs 中定义了output对象...observe

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 时,我总是最终将每个动态组件定义为一个模块,即使我知道该组件只会有一个实例。它使跟踪哪些inputoutputid 属于哪个页面变得更加容易 - 因为除非我选择让它们可见,否则它们对所有其他组件都是不可见的。


推荐阅读