R Academy · Lektion

Dynamiskt UI med renderUI och insertUI

Generera UI-element dynamiskt utifrån användarindata och serverns tillstånd.

Lektion 3 av 413 steg

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ån renderUI() 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 hantera NULL innan 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]])
  })
}
Gratis att börja

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

  1. Fördjupning i reaktiv programmering
  2. Shiny-moduler för kodåteranvändning
  3. Dynamiskt UI med renderUI och insertUI
  4. Distribuera Shiny-appar
← Tillbaka till R Academy