Search code examples
rshinybslib

R Shiny app: output flashes out after changing the position in UI


I am new to R Shiny and currently reading about the clicking behaviour, chapter 7 of the book Mastering Shiny.

I don't understand why after changing the location of tableOutput() in UI will cause a flash out effect on the outputs?

The shared component:

library(shiny)
library(bslib)

server <- function(input, output, session) {
  
  output$plot <- renderPlot({
    plot(mtcars$wt, mtcars$mpg)
  }, res = 96)
  
  output$info <- renderPrint({
    req(input$plot_click)
    x <- round(input$plot_click$x, digits = 2)
    y <- round(input$plot_click$y, digits = 2)
    cat("[", x, ", ", y, " ]", sep = "")
  })
  
  output$data <- renderTable({
    nearPoints(mtcars, coordinfo = input$plot_click, xvar = "wt", yvar = "mpg")
  })
  
}

shinyApp(ui, server)

This UI works, but the output is squashed. I'd like to place it below the main plot:

ui <- page_sidebar(
  
  sidebar = sidebar(
    title = "Global controls",
    
    varSelectInput(inputId = "x", label = "X:", data = df),
    
    varSelectInput(inputId = "y", label = "Y:", data = df)
  ),
  
  card(
    full_screen = TRUE,
    layout_sidebar(
      sidebar = sidebar(
        title = "Coordinate of where you click:",
        position = "left",
        
        verbatimTextOutput(outputId = "info"),

        ########### the position of this line #################
        tableOutput(outputId = "data")
        #######################################################
      ),
      
      plotOutput(outputId = "plot", click = "plot_click")
    )
  )
)

enter image description here

This UI doesn't work properly, as the output disappears after a quick flash. In addition, the other output verbatimTextOutput() also disappeared:

ui <- page_sidebar(
  
  sidebar = sidebar(
    title = "Global controls",
    
    varSelectInput(inputId = "x", label = "X:", data = df),
    
    varSelectInput(inputId = "y", label = "Y:", data = df)
  ),
  
  card(
    full_screen = TRUE,
    layout_sidebar(
      sidebar = sidebar(
        title = "Coordinate of where you click:",
        position = "left",
        
        verbatimTextOutput(outputId = "info")
      ),
      
      plotOutput(outputId = "plot", click = "plot_click"),

      ########### the position of this line #################
      tableOutput(outputId = "data")
      #######################################################

    )
  )
)

enter image description here

It would be much appreciated if someone can explain what caused this behaviour, and how I can correct it.


Solution

  • If you click on the plot, then the nearPoints table is filled below the plotOutput. This causes the plot to resize and re-render. However, this sets input$plot_click to NULL and therefore the output immediately disappears.

    What you need here is cancelOutput = TRUE in req() for all relevant render calls. From ?req:

    cancelOutput: If TRUE and an output is being evaluated, stop processing as usual but instead of clearing the output, leave it in whatever state it happens to be in.

    enter image description here

    library(shiny)
    library(bslib)
    
    ui <- page_sidebar(
      
      sidebar = sidebar(
        title = "Global controls",
        
        varSelectInput(inputId = "x", label = "X:", data = df),
        
        varSelectInput(inputId = "y", label = "Y:", data = df)
      ),
      
      card(
        full_screen = TRUE,
        layout_sidebar(
          sidebar = sidebar(
            title = "Coordinate of where you click:",
            position = "left",
            
            verbatimTextOutput(outputId = "info")
          ),
          
          plotOutput(outputId = "plot", click = "plot_click"),
          
          ########### the position of this line #################
          tableOutput(outputId = "data")
          #######################################################
          
        )
      )
    )
    
    
    server <- function(input, output, session) {
      
      output$plot <- renderPlot({
        plot(mtcars$wt, mtcars$mpg)
      }, res = 96)
      
      output$info <- renderPrint({
        req(input$plot_click, cancelOutput = TRUE)
        x <- round(input$plot_click$x, digits = 2)
        y <- round(input$plot_click$y, digits = 2)
        cat("[", x, ", ", y, " ]", sep = "")
      })
      
      output$data <- renderTable({
        req(input$plot_click, cancelOutput = TRUE)
        nearPoints(mtcars, coordinfo = input$plot_click, xvar = "wt", yvar = "mpg")
      })
      
    }
    
    shinyApp(ui, server)