更新输入并在watchEvent中更改ui

时间:2020-06-20 14:49:29

标签: r shiny shiny-reactivity

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

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

第三部分对我不起作用。我定义了一个actionButton,在单击该按钮时,我会触发两个watchEvent:第一个带有updateTextInput的事件,第二个更新页面的事件。问题是input$text未被更新-好像updateTextInput被忽略了。

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

有什么办法让按钮既可以更新文本又可以切换用户界面?这都是我正在制作的更大应用程序的一部分,但是下面的示例重现了该问题。

# 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)

1 个答案:

答案 0 :(得分:1)

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

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

我更改了服务器功能,以便在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对象。这绝不是一个好主意。我看这是否是根本原因...

更新

此服务器功能是否提供您想要的行为?如果是这样,那么您的问题是因为您在output rs中定义了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时,我总是最终将每个动态组件都定义为一个模块,即使我知道组件永远只有一个实例也是如此。它使跟踪inputoutput哪些ID属于哪个页面变得更加容易-因为除非我选择使它们可见,否则它们对于其他所有组件都是不可见的。