Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

How can I switch between page layouts in Shiny in response to user input? For example, I would like to switch between a sidebar layout to a wellpanel layout in order to have the graphics be able to span the entire page.

What I have so far seems to be on the verge of working, but I think the issue is that I can't reuse interfaces created from renderUI. Here is an example,

library(shiny)

shinyApp(
    shinyUI(
        fluidPage(
            radioButtons('layout', 'Layout:', choices=c('Sidebar', 'WellPanel'), inline=TRUE),
            conditionalPanel(
                condition = "input.layout == 'Sidebar'",
                uiOutput('sidebarUI')
            ),
            conditionalPanel(
                condition = "input.layout == 'WellPanel'",
                uiOutput('wellUI')
            )
        )
    ),
    shinyServer(function(input, output) {
        output$sidebarUI <- renderUI({
            sidebarLayout(
                sidebarPanel(
                    uiOutput('ui')
                ),
                mainPanel(
                    plotOutput('plot')
                )
            )
        })

        output$wellUI <- renderUI({
            fluidRow(
                column(12, plotOutput('plot')),
                column(12, wellPanel(uiOutput('ui')))
            )
        })

        output$ui <- renderUI({
            list(
                checkboxInput('inp1', 'Some stuff'),
                sliderInput('inp2', 'Some more stuff', 0, 10, 5)
            )
        })

        output$plot <- renderPlot({ plot(1) })
    })
)

If either one of the conditional panels is commented out, then the other one works, but only one will work with both conditional panels. How is this done?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
1.1k views
Welcome To Ask or Share your Answers For Others

1 Answer

Hi you can't call an output twice (or more) in the ui, that's why this isn't working, instead you can do all the work in the server like this :

library(shiny)

shinyApp(
  shinyUI(
    fluidPage(
      radioButtons('layout', 'Layout:', choices=c('Sidebar', 'WellPanel'), inline=TRUE),
      uiOutput('general_ui')
    )
  ),
  shinyServer(function(input, output) {
    output$general_ui <- renderUI({
      if (input$layout == "Sidebar") {
        sidebarLayout(
          sidebarPanel(
            uiOutput('ui')
          ),
          mainPanel(
            plotOutput('plot')
          )
        )
      } else if (input$layout == "WellPanel") {
        fluidRow(
          column(12, plotOutput('plot')),
          column(12, wellPanel(uiOutput('ui')))
        )
      }
    })

    output$ui <- renderUI({
      list(
        checkboxInput('inp1', 'Some stuff'),
        sliderInput('inp2', 'Some more stuff', 0, 10, 5)
      )
    })

    output$plot <- renderPlot({ plot(1) })
  })
)

But there's a catch, when you switch between layout, the input widgets are reinitialized...

But you can fix it with something like this :

output$ui <- renderUI({
  list(
    checkboxInput('inp1', 'Some stuff'),
    if (is.null(input$inp2)) {
      sliderInput('inp2', 'Some more stuff', 0, 10, 5)
    } else {
      sliderInput('inp2', 'Some more stuff', 0, 10, input$inp2)
    }
  )
})

Before creating your widget, you'll have to check if the value already exists, in a more compact way than above you can do that :

output$ui <- renderUI({
      list(
        checkboxInput(inputId = "inp1", label = 'Some stuff', value = input$inp1 %||% FALSE),
        sliderInput(inputId = "inp2", label = 'Some more stuff', min = 0, max = 10, value = input$inp2 %||% 5)
      )
    })

With %||% function defined like this :

`%||%` <- function(a, b) {
  if (!is.null(a)) a else b
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...