2

I'm trying to get the following to work within a Shiny App:

  1. There are two pages, each defined by a different UI
  2. The first page shown has a textInput with some default text (ie, textInput("text", "Text Input", "word"))
  3. When a user clicks a button: (1) the value of input$text gets updated via updateTextInput and (2) the page switches.

The third part isn't working for me. I've defined an actionButton, where when that is clicked I have two observeEvents that get triggered: the first one with updateTextInput, and a second one that updates the page. The problem is that input$text isn't being updated - it seems as though the updateTextInput is being ignored.

When I comment out the observeEvent that switches the ui, the updateTextInput works as expected.

Any idea how to get the button to both update the text then switch the UI? This is all part of a larger App I'm making, but the below example reproduces the issue.

# 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 Answer 1

1

I hate to give an answer along the lines of "this works, but I don't know why", but...

This works and I don't know why.

I changed your server function so that the word to display on page 2 is stared in a reactiveValues object. No other changes.

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

But in pasting this in here, I noticed you've defined output objects inside your observers. That's never a good idea. I'll see if that's the root cause...

Update

Does this server function give you the behaviour you want? If so, your problem was because you defined your output objects inside your observers...

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

As an aside, whenever I write this sort of dynamic UI, I always end up defining each dynamic component as a module, even if I know there will only ever be one instance of the component. It makes keeping track of which input and output ids belong to which page much easier - because they're invisible to every other component unless I choose to make them visible.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.