Dynamiskt UI med renderUI och insertUI
Generera UI-element dynamiskt utifrån användarindata och serverns tillstånd.
Dynamiskt UI med renderUI och insertUI är en gratis lektion i R Academy på CoddyKit. Detta är lektion 3 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för R Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i R Academy innehåller totalt 4 lektioner.
Dynamiskt UI — varför och när
Ibland kan det UI ni behöver inte fastställas helt när appen startar — det beror på användarens val, inlästa data eller förhållanden under körning. Shiny har två mekanismer: renderUI() för att ersätta hela innehållet i en platshållare och insertUI()/removeUI() för att lägga till eller ta bort element utan att ersätta allt.
library(shiny)
# Static UI: columns always shown
# ui <- fluidPage(selectInput('x', ...), selectInput('y', ...))
# Dynamic UI: columns depend on which dataset was loaded
# ui <- fluidPage(fileInput('upload', ...), uiOutput('var_selectors'))renderUI() och uiOutput()
renderUI({...}) i servern bygger och returnerar ett UI-element reaktivt. uiOutput('id') i UI:t skapar en platshållare som visar det som renderUI producerar. Hela innehållet i platshållaren ersätts varje gång den reaktiva koden körs igen.
ui <- fluidPage(
selectInput('dataset', 'Dataset:', choices = c('iris', 'mtcars')),
uiOutput('column_selector') # placeholder
)
server <- function(input, output, session) {
output$column_selector <- renderUI({
df <- get(input$dataset) # reactive dependency on dataset
selectInput('col', 'Choose Column:',
choices = names(df))
})
}
shinyApp(ui, server)renderUI() med flera kontroller
Returnera en tagList() från renderUI() för att återge flera UI-element samtidigt. Detta är standardmönstret när antalet kontroller beror på data — till exempel när ni genererar ett filter per kolumn i ett dataset.
server <- function(input, output, session) {
output$filters <- renderUI({
df <- get(input$dataset)
nums <- names(df)[sapply(df, is.numeric)]
# One slider per numeric column
sliders <- lapply(nums, function(col) {
rng <- range(df[[col]], na.rm = TRUE)
sliderInput(
inputId = paste0('filter_', col),
label = col,
min = rng[1], max = rng[2],
value = rng
)
})
tagList(sliders) # render all sliders
})
}insertUI() — Lägg till element dynamiskt
insertUI(selector, where, ui) infogar ett UI-element i DOM:en utan att bygga om hela sidan. Använd CSS-selektorer för att ange var elementet ska infogas. where kan vara 'afterEnd', 'beforeEnd', 'afterBegin' eller 'beforeBegin'.
server <- function(input, output, session) {
item_count <- reactiveVal(0)
observeEvent(input$add_item, {
item_count(item_count() + 1)
id <- paste0('item_', item_count())
insertUI(
selector = '#item_container', # CSS selector
where = 'beforeEnd',
ui = div(
id = id,
style = 'padding: 5px; border: 1px solid #ccc; margin: 3px;',
textInput(id, paste('Item', item_count()), value = '')
)
)
})
}removeUI() — Ta bort element
removeUI(selector) tar bort det första DOM-elementet som matchar CSS-selektorn. Använd multiple = TRUE för att ta bort alla matchande element. Detta kompletterar insertUI() i listbaserade UI:n där användare kan lägga till och ta bort objekt.
server <- function(input, output, session) {
observeEvent(input$remove_last, {
# Remove the last item div
n <- isolate(item_count())
if (n > 0) {
removeUI(selector = paste0('#item_', n))
item_count(n - 1)
}
})
observeEvent(input$clear_all, {
# Remove all items matching a class
removeUI(selector = '.dynamic-item', multiple = TRUE)
item_count(0)
})
}conditionalPanel() — Synlighet på klientsidan
conditionalPanel(condition, ...) visar eller döljer UI-element baserat på ett JavaScript-villkor som utvärderas i webbläsaren. Till skillnad från renderUI() finns elementen alltid i DOM:en — de är bara synliga eller dolda. Detta är snabbare för enkel visningslogik eftersom ingen tur och retur till servern behövs.
ui <- fluidPage(
selectInput('plot_type', 'Plot Type:',
choices = c('scatter', 'histogram', 'boxplot')),
# Only shown when scatter is selected
conditionalPanel(
condition = "input.plot_type == 'scatter'",
selectInput('x_var', 'X Variable:', choices = names(mtcars)),
selectInput('y_var', 'Y Variable:', choices = names(mtcars))
),
# Only shown when histogram is selected
conditionalPanel(
condition = "input.plot_type == 'histogram'",
sliderInput('bins', 'Number of bins:', 5, 50, 20)
),
plotOutput('main_plot')
)updateSelectInput() — Ändra befintliga indata
I stället för att ersätta en hel inmatningskontroll kan ni använda updateSelectInput(session, id, choices, selected) för att endast uppdatera valen eller det valda värdet i en befintlig selectInput. Liknande uppdateringsfunktioner finns för alla indatatyper: updateSliderInput(), updateTextInput() och så vidare.
server <- function(input, output, session) {
# When dataset changes, update the column selector
observeEvent(input$dataset, {
df <- get(input$dataset)
updateSelectInput(
session = session,
inputId = 'column',
choices = names(df),
selected = names(df)[1]
)
})
# Reset slider when reset button pressed
observeEvent(input$reset_btn, {
updateSliderInput(session, 'n_items',
value = 20, min = 1, max = 100)
})
}updateSliderInput() och updateNumericInput()
Uppdateringsfunktioner skickar ett meddelande till webbläsaren för att ändra det aktuella värdet, minvärdet, maxvärdet eller etiketten för en befintlig inmatning. Detta är effektivare än att ta bort och återskapa kontrollen med renderUI(), och kontrollens position i sidlayouten bevaras.
server <- function(input, output, session) {
# When data loads, set slider max to actual data length
observeEvent(input$load_data, {
data <- readRDS(input$upload$datapath)
updateSliderInput(session, 'row_slider',
min = 1,
max = nrow(data),
value = c(1, min(50, nrow(data)))
)
updateNumericInput(session, 'page_size',
max = nrow(data),
value = min(10, nrow(data))
)
})
}Kom åt renderUI-indata med req()
Indata som skapas dynamiskt med renderUI() är NULL tills de har återgetts. Använd req(input$dynamic_input) i all serverkod som är beroende av dynamiskt skapade indata för att förhindra fel under initieringen.
server <- function(input, output, session) {
# dynamic input: 'col' is created by renderUI
output$column_selector <- renderUI({
selectInput('col', 'Column:', choices = names(get(input$dataset)))
})
output$summary_stats <- renderPrint({
req(input$col) # wait until 'col' exists
req(input$dataset) # and dataset is chosen
df <- get(input$dataset)
summary(df[[input$col]])
})
}Dynamiska flikar med appendTab()
appendTab(inputId, tab, select) lägger till en ny flik i en tabsetPanel() under körning. removeTab(inputId, target) tar bort en flik. Detta mönster möjliggör arbetsflöden där användare öppnar, stänger och växlar mellan dynamiskt genererade analysvyer.
ui <- fluidPage(
actionButton('add_tab', 'Open New Analysis Tab'),
tabsetPanel(id = 'analysis_tabs', type = 'tabs')
)
server <- function(input, output, session) {
tab_count <- reactiveVal(0)
observeEvent(input$add_tab, {
tab_count(tab_count() + 1)
n <- tab_count()
appendTab(
inputId = 'analysis_tabs',
select = TRUE,
tab = tabPanel(
title = paste('Analysis', n),
value = paste0('tab_', n),
plotOutput(paste0('plot_', n)),
actionButton(paste0('close_', n), 'Close')
)
)
})
}renderUI jämfört med insertUI — när ska de användas?
Välj rätt verktyg utifrån användningsfallet:
- renderUI(): Ersätt hela innehållet i en platshållare reaktivt. Bäst när hela blocket ändras samtidigt.
- insertUI(): Lägg till nya element i befintligt innehåll. Bäst för växande listor där ni inte vill återge allt igen.
- updateXxxInput(): Ändra en befintlig inmatning på plats. Bäst när val eller värden ska ändras utan att inmatningen återges igen.
- conditionalPanel(): Visa eller dölj utan tur och retur till servern. Bäst för enkel visningslogik.
# Decision guide:
# - 'Show filter only when advanced mode' -> conditionalPanel
# - 'Populate column choices from loaded CSV' -> updateSelectInput
# - 'Show different controls per selected tab' -> renderUI
# - 'Add a row editor for each row user adds' -> insertUI
# - 'Remove a row editor' -> removeUI
# Combining strategies:
server <- function(input, output, session) {
# Use renderUI for column selectors (replaces whole block)
output$col_selectors <- renderUI({ ... })
# Use insertUI for dynamically added rows
observeEvent(input$add_row, { insertUI(...) })
# Use conditionalPanel for show/hide (in UI, no server code)
}Snabb kontroll
Vad är den viktigaste skillnaden mellan renderUI() och insertUI() när ni bygger dynamiskt UI i Shiny?
Repetition av dynamiskt UI
Viktiga slutsatser från Dynamiskt UI med renderUI och insertUI:
renderUI({}) + uiOutput('id'): ersätt hela innehållet i en platshållare reaktivt.- Returnera
tagList()frånrenderUI()för att återge flera element samtidigt. insertUI(selector, where, ui): infoga element på valfri plats i DOM:en.removeUI(selector): ta bort element med en CSS-selektor.conditionalPanel(condition, ...): visa eller dölj på klientsidan utan servern.updateSelectInput(),updateSliderInput(): ändra befintliga indata på plats.- Använd alltid
req(input$dynamic_id)för att hanteraNULLinnan dynamiska indata har återgetts.
# Typical pattern: dynamic column selector
ui <- fluidPage(
fileInput('upload', 'Upload CSV'),
uiOutput('col_ui'), # placeholder
plotOutput('col_plot')
)
server <- function(input, output, session) {
df <- reactive({
req(input$upload)
read.csv(input$upload$datapath)
})
output$col_ui <- renderUI({
req(df())
selectInput('col', 'Column:', choices = names(df()))
})
output$col_plot <- renderPlot({
req(input$col)
hist(df()[[input$col]])
})
}Lär dig R med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 43
- Lektioner
- 159
Vanliga frågor
Är lektionen ”Dynamiskt UI med renderUI och insertUI” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen R Academy, inklusive ”Dynamiskt UI med renderUI och insertUI”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i R Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Dynamiskt UI med renderUI och insertUI”?
Generera UI-element dynamiskt utifrån användarindata och serverns tillstånd. Ni övar på R Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig R Academy?
Du behöver inga förkunskaper. Utbildningen i R Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.
Hur lång tid tar lektionen ”Dynamiskt UI med renderUI och insertUI”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här R Academy-lektionen?
Ja. Varje R Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Fördjupning i reaktiv programmering
- Shiny-moduler för kodåteranvändning
- Dynamiskt UI med renderUI och insertUI
- Distribuera Shiny-appar