如何使Shiny App UI根据URL参数或窗口宽度切换输入组件?
Great question! Let’s break down your two main concerns one by one, with practical code examples for each scenario.
1. Switching UI via URL Parameter (mini=TRUE)
You absolutely can use either conditionalPanel or renderUI for this—each has its own use case:
Option 1: renderUI (Server-Side Approach)
This is the more flexible option if you need to tie the URL parameter to other server-side logic. We’ll read the URL query string in the server, then dynamically render the right input component:
library(shiny) library(shinyWidgets) nazwy <- c('Warszawa', 'Krakow', 'Gdansk') ui <- fluidPage( uiOutput("city_selector") ) server <- function(input, output, session) { # Grab the `mini` parameter from the URL is_mini_mode <- reactive({ query_params <- parseQueryString(session$clientData$url_search) # Convert to boolean, handle cases where parameter is missing or malformed isTRUE(as.logical(query_params$mini)) }) output$city_selector <- renderUI({ if (is_mini_mode()) { pickerInput(inputId = "miasto", choices = nazwy, multiple = TRUE) } else { checkboxGroupInput('miasto', 'Wybierz miasto:', choices = nazwy) } }) } shinyApp(ui, server)
Option 2: conditionalPanel (Client-Side Approach)
If you don’t need server-side logic for this switch, conditionalPanel lets you handle everything directly in the UI using JavaScript to read the URL. This keeps the server code cleaner:
library(shiny) library(shinyWidgets) nazwy <- c('Warszawa', 'Krakow', 'Gdansk') ui <- fluidPage( # Show pickerInput when URL has `mini=TRUE` conditionalPanel( condition = "window.location.search.includes('mini=TRUE')", pickerInput(inputId = "miasto", choices = nazwy, multiple = TRUE) ), # Show checkboxGroupInput otherwise conditionalPanel( condition = "!window.location.search.includes('mini=TRUE')", checkboxGroupInput('miasto', 'Wybierz miasto:', choices = nazwy) ) ) server <- function(input, output, session) { # Add your app logic here } shinyApp(ui, server)
Pro tip: If you need to handle case variations (like Mini=true), adjust the JS condition to use toLowerCase(): window.location.search.toLowerCase().includes('mini=true')
2. Switching UI Based on Window Width
Yes, you can absolutely swap components based on window size! The key gotcha here is that resizing the window will trigger a re-render of conditionalPanel components, which can reset user selections. To fix this, we’ll store the selected value in a reactive variable and sync it across both input components.
Here’s the refined solution that preserves user choices:
library(shiny) library(shinyWidgets) nazwy <- c('Warszawa', 'Krakow', 'Gdansk') ui <- fluidPage( # Show pickerInput for mobile (window < 768px, a common breakpoint) conditionalPanel( condition = "window.innerWidth < 768", pickerInput(inputId = "miasto_mobile", choices = nazwy, multiple = TRUE) ), # Show checkboxGroupInput for desktop (window >= 768px) conditionalPanel( condition = "window.innerWidth >= 768", checkboxGroupInput('miasto_desktop', 'Wybierz miasto:', choices = nazwy) ) ) server <- function(input, output, session) { # Reactive variable to store the user's selected cities (persists across switches) selected_cities <- reactiveVal(nazwy[1]) # Default to first city # Sync mobile input changes to the reactive variable and desktop input observeEvent(input$miasto_mobile, { selected_cities(input$miasto_mobile) updateCheckboxGroupInput(session, "miasto_desktop", selected = input$miasto_mobile) }) # Sync desktop input changes to the reactive variable and mobile input observeEvent(input$miasto_desktop, { selected_cities(input$miasto_desktop) updatePickerInput(session, "miasto_mobile", selected = input$miasto_desktop) }) # Initialize both inputs with the default value observe({ updatePickerInput(session, "miasto_mobile", selected = selected_cities()) updateCheckboxGroupInput(session, "miasto_desktop", selected = selected_cities()) }) # Example: Print selected cities to the console for testing observe({ cat("Selected cities:", paste(selected_cities(), collapse = ", "), "\n") }) } shinyApp(ui, server)
By using separate input IDs for mobile/desktop and syncing their values to selected_cities, we ensure users don’t lose their selections when resizing the window.
Quick Recap
- URL parameter switch: Both
renderUI(server-side) andconditionalPanel(client-side) work. ChooserenderUIif you need server logic tied to the parameter,conditionalPanelfor a lighter client-only approach. - Window width switch: Use
conditionalPanelwith a reactive variable to store selections—this prevents resets and keeps the user experience smooth.
内容的提问来源于stack exchange,提问作者MonikaP

