Обновите ввод и измените пользовательский интерфейс в ObservEvent - PullRequest
0 голосов
/ 20 июня 2020

Я пытаюсь заставить следующее работать в Shiny App:

  1. Есть две страницы, каждая из которых определяется другим пользовательским интерфейсом
  2. Первая показанная страница имеет textInput с некоторым текстом по умолчанию (ie, textInput("text", "Text Input", "word"))
  3. Когда пользователь нажимает кнопку: (1) значение input$text обновляется через updateTextInput и (2) страница переключается.

Третья часть у меня не работает. Я определил actionButton, при нажатии на который у меня срабатывают два наблюдаемых события: первое с updateTextInput и второе, обновляющее страницу. Проблема в том, что input$text не обновляется - кажется, что updateTextInput игнорируется.

Когда я комментирую ObserverEvent, который переключает пользовательский интерфейс, 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 Ответ

1 голос
/ 20 июня 2020

Ненавижу давать ответ типа «это работает, но я не знаю почему», но ...

Это работает, и я не знаю почему.

Я изменил функцию вашего сервера, чтобы слово, отображаемое на странице 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 внутри своих наблюдателей. Это никогда не бывает хорошей идеей. Я посмотрю, является ли причина root ...

Обновление

Эта функция сервера дает вам желаемое поведение? Если это так, ваша проблема заключалась в том, что вы определили свои output объекты внутри своего observe rs ...

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

В стороне, всякий раз, когда я пишу такого рода динамический c UI, я всегда В конечном итоге каждый компонент Dynami c определяется как модуль, даже если я знаю, что когда-либо будет только один экземпляр компонента. Это значительно упрощает отслеживание того, какие идентификаторы input и output принадлежат какой странице - потому что они невидимы для всех других компонентов, если я не сделаю их видимыми.

...