MutliPage Shiny App


#1

Hi,

Is there any recommended & safe way to create multipage Shiny Applications?

Since Shiny is using reactive programming - it would be okay to me if there were no redirection at all from one page to another..

What I want to achieve is that when there is a button, say, and a user clicks on that, then the whole UI is replaced with a different one. It might be that the other layout of the other page will be very different - but I want to make sure that the reactive values are not re-initialised over and over again when switching between pages..

My very first idea was that I can migrate the whole UI into the server function and based on some reactive value, the appropriate UI will appear in the browser. This works great - but I am not really certain about 2 things:

  • Can we use the same outputid in multiple UI? Say, there is a plot that I would like to insert in both UI - but it would not be optimal to insert multiple render functions

  • Is there a way not to re-initalise everything when switching between the pages? When I switch from page 1 to page 2, it looks like everything is reinitalised. When I work with tabs, then once a plot has been rendered, it is fast to navigate between them because it does not rerender. It does not work with renderUI though..

That would be very important in my case because I would like to build some dashboard where multiple tables can be edited through bootstrap Modals - and I would like to supply the users with an extremely clear structure. So tabs would not be helpful in my case. However, I would like to make sure that once a page is opened once - then it does NOT rerender everything from scratch.

Since Rshiny's reactivity is essentially based on 'laziness' - i.e. the R code within a reactive expression is not executed unless its called by some function - creating a large number of reactive expressions does do any harm. (Say, there is only one reactive expression for each page)

Apart from this, I wonder if there is a way to disable this laziness - that would not be optimal for several reasons, but if it is computationally expensive the generate the "object" that a reactive value returns - but its memory consumption is small and it would be visualised in the fifth page, say, then it would be great if it could be generated while the user navigates between the pages.

Here is a minimal example that shows that the page is always re-initalised:

library(shiny)
library(datasets)

#UI
ui <- fluidPage(
  actionButton("btn1", label = "Switch UI"),
  uiOutput("uiPage")
)

server <- function(input, output, server){
  
  
  output$uiPage <- renderUI({
    
    if(input$btn1 %in% c(1,3,5)){
    fluidPage(    
    titlePanel("Telephones by region"),
        sidebarLayout(      
      

      sidebarPanel(
        selectInput("region", "Region:", 
                    choices=colnames(WorldPhones)),
        hr(),
        helpText("Data from AT&T (1961) The World's Telephones.")
      ),
      
      # Create a spot for the barplot
      mainPanel(
        plotOutput("Plot1"), 
        actionButton("btn2", "HERE")
      )
      
    )
    )
    }else{
      fluidPage(    
        titlePanel("Airpassangers"),
        plotOutput("Plot2")  
        
        
      )
    }
  })
  
  #Plot1 is for the Page1
  output$Plot1 <- renderPlot({
    #Print the value of Button2
    print(input$btn2)

    barplot(WorldPhones[,input$region]*1000, 
            main=input$region,
            ylab="Number of Telephones",
            xlab="Year")
  })

  #Plot2 is for the Page2  
  output$Plot2 <- renderPlot({
    plot(AirPassengers)
  })
  
}


shinyApp(ui, server)


Thanks in advance,

Tamas