0Pricing
R Academy · Lezione

Interfaccia dinamica con renderUI e insertUI

Generi elementi dell'interfaccia al volo in base all'input dell'utente e allo stato del server

Interfaccia dinamica con renderUI e insertUI è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.

UI dinamica — Perché e quando

A volte la UI necessaria non può essere determinata completamente all'avvio dell'app: dipende dalle scelte dell'utente, dai dati caricati o dalle condizioni di runtime. Shiny offre due meccanismi: renderUI() per sostituire interamente il contenuto di un segnaposto e insertUI()/removeUI() per aggiungere o rimuovere elementi senza sostituire tutto.

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() e uiOutput()

renderUI({...}) nel server costruisce e restituisce reattivamente un elemento UI. uiOutput('id') nella UI crea un segnaposto che visualizza ciò che produce renderUI. L'intero contenuto del segnaposto viene sostituito ogni volta che il reattivo viene rieseguito.

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() con più controlli

Restituisca una tagList() da renderUI() per visualizzare più elementi UI contemporaneamente. Questo è il modello standard quando il numero di controlli dipende dai dati, ad esempio per generare un filtro per ogni colonna di un 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() — Aggiunta dinamica di elementi

insertUI(selector, where, ui) inserisce un elemento UI nel DOM senza ricostruire l'intera pagina. Utilizzi i selettori CSS per identificare il punto di inserimento. where può essere 'afterEnd', 'beforeEnd', 'afterBegin' oppure '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() — Eliminazione di elementi

removeUI(selector) rimuove il primo elemento DOM che corrisponde al selettore CSS. Utilizzi multiple = TRUE per rimuovere tutti gli elementi corrispondenti. È il complemento di insertUI() per le UI basate su elenchi, in cui gli utenti possono aggiungere e rimuovere elementi.

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() — Visibilità lato client

conditionalPanel(condition, ...) mostra o nasconde gli elementi UI in base a una condizione JavaScript valutata nel browser. A differenza di renderUI(), gli elementi sono sempre presenti nel DOM: vengono semplicemente visualizzati o nascosti. È più rapido per una semplice logica di visualizzazione e occultamento, perché non richiede un viaggio di andata e ritorno al server.

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() — Modifica degli input esistenti

Anziché sostituire un intero controllo di input, utilizzi updateSelectInput(session, id, choices, selected) per aggiornare solo le scelte o il valore selezionato di un selectInput esistente. Funzioni di aggiornamento analoghe esistono per tutti i tipi di input: updateSliderInput(), updateTextInput() e così via.

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() e updateNumericInput()

Le funzioni di aggiornamento inviano un messaggio al browser per modificare il valore corrente, il minimo, il massimo o l'etichetta di un input esistente. È più efficiente che distruggere e ricreare il controllo con renderUI() e ne preserva la posizione nel layout della pagina.

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))
    )
  })
}

Accesso agli input di renderUI con req()

Gli input creati dinamicamente con renderUI() sono NULL finché non vengono visualizzati. Utilizzi req(input$dynamic_input) in qualsiasi codice server che dipenda da input creati dinamicamente, per prevenire errori durante l'inizializzazione.

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]])
  })
}

Schede dinamiche con appendTab()

appendTab(inputId, tab, select) aggiunge una nuova scheda a un tabsetPanel() durante l'esecuzione. removeTab(inputId, target) ne rimuove una. Questo modello consente flussi di lavoro in cui gli utenti aprono, chiudono e alternano viste di analisi generate dinamicamente.

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 e insertUI — Quando utilizzare l'uno o l'altro

Scelga lo strumento giusto in base al caso d'uso:

  • renderUI(): sostituisce reattivamente l'intero contenuto di un segnaposto. È ideale quando l'intero blocco cambia contemporaneamente.
  • insertUI(): aggiunge nuovi elementi al contenuto esistente. È ideale per elenchi che crescono e che non si desidera visualizzare nuovamente per intero.
  • updateXxxInput(): modifica un input esistente direttamente sul posto. È ideale per cambiare scelte o valori senza eseguire nuovamente il rendering.
  • conditionalPanel(): mostra o nasconde senza un viaggio di andata e ritorno al server. È ideale per una semplice logica di visibilità.
# 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)
}

Verifica rapida

Qual è la differenza fondamentale tra renderUI() e insertUI() per creare una UI dinamica in Shiny?

Riepilogo della UI dinamica

Punti chiave della UI dinamica con renderUI e insertUI:

  • renderUI({}) + uiOutput('id'): sostituisce reattivamente l'intero contenuto di un segnaposto.
  • Restituisca tagList() da renderUI() per visualizzare più elementi contemporaneamente.
  • insertUI(selector, where, ui): inserisce elementi in qualsiasi posizione del DOM.
  • removeUI(selector): rimuove elementi tramite selettore CSS.
  • conditionalPanel(condition, ...): mostra o nasconde gli elementi lato client senza ricorrere al server.
  • updateSelectInput(), updateSliderInput(): modificano gli input esistenti direttamente sul posto.
  • Utilizzi sempre req(input$dynamic_id) per gestire il valore NULL prima del rendering degli input dinamici.
# 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]])
  })
}

Domande Frequenti

La lezione «Interfaccia dinamica con renderUI e insertUI» è gratuita?

Sì — il testo completo di «Interfaccia dinamica con renderUI e insertUI» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.

Cosa imparerò in «Interfaccia dinamica con renderUI e insertUI»?

Generi elementi dell'interfaccia al volo in base all'input dell'utente e allo stato del server Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare R Academy?

Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Interfaccia dinamica con renderUI e insertUI»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione R Academy?

Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Approfondimento della programmazione reattiva
  2. Moduli Shiny per riutilizzare il codice
  3. Interfaccia dinamica con renderUI e insertUI
  4. Distribuzione delle app Shiny
← Torna a R Academy