0Pricing
R Academy · Aula

Interface dinâmica com renderUI e insertUI

Gere elementos da interface dinamicamente com base na entrada do usuário e no estado do servidor.

Interface dinâmica com renderUI e insertUI é uma aula grátis de R Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de R Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de R Academy inclui 4 aulas no total.

Interface dinâmica — Por quê e quando

Às vezes, a interface necessária não pode ser totalmente determinada na inicialização do aplicativo — ela depende das escolhas do usuário, dos dados carregados ou das condições de execução. O Shiny oferece dois mecanismos: renderUI() para substituir todo o conteúdo de um espaço reservado e insertUI()/removeUI() para adicionar ou remover elementos sem substituir tudo.

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({...}) no servidor cria e retorna um elemento de interface de forma reativa. uiOutput('id') na interface cria um espaço reservado que exibe o que for produzido por renderUI. Todo o conteúdo do espaço reservado é substituído cada vez que o reativo é executado novamente.

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() com vários controles

Retorne uma tagList() de renderUI() para renderizar vários elementos da interface de uma só vez. Esse é o padrão usual quando o número de controles depende dos dados — por exemplo, gerar um filtro para cada coluna de um conjunto de dados.

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() — Adicionar elementos dinamicamente

insertUI(selector, where, ui) insere um elemento da interface no DOM sem reconstruir a página inteira. Use seletores CSS para indicar o ponto de inserção. where pode ser 'afterEnd', 'beforeEnd', 'afterBegin' ou '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() — Excluir elementos

removeUI(selector) remove o primeiro elemento do DOM que corresponde ao seletor CSS. Use multiple = TRUE para remover todos os elementos correspondentes. Essa é a operação complementar a insertUI() em interfaces baseadas em listas, nas quais os usuários podem adicionar e remover itens.

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() — Visibilidade no cliente

conditionalPanel(condition, ...) mostra ou oculta elementos da interface com base em uma condição JavaScript avaliada no navegador. Diferentemente de renderUI(), os elementos estão sempre no DOM — apenas visíveis ou ocultos. Isso é mais rápido para uma lógica simples de exibição e ocultação, pois não exige uma ida e volta ao servidor.

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() — Modificar entradas existentes

Em vez de substituir todo um controle de entrada, use updateSelectInput(session, id, choices, selected) para atualizar apenas as opções ou o valor selecionado de um selectInput existente. Há funções de atualização semelhantes para todos os tipos de entrada: updateSliderInput(), updateTextInput() etc.

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

As funções de atualização enviam uma mensagem ao navegador para modificar o valor atual, o mínimo, o máximo ou o rótulo de uma entrada existente. Isso é mais eficiente do que destruir e recriar o controle com renderUI() e preserva a posição do controle no layout da página.

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

Acessando entradas de renderUI com req()

As entradas criadas dinamicamente com renderUI() são NULL até serem renderizadas. Use req(input$dynamic_input) em qualquer código do servidor que dependa de entradas criadas dinamicamente para evitar erros durante a inicialização.

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

Abas dinâmicas com appendTab()

appendTab(inputId, tab, select) adiciona uma nova aba a um tabsetPanel() durante a execução. removeTab(inputId, target) remove uma aba. Esse padrão permite fluxos de trabalho nos quais os usuários abrem, fecham e alternam entre visualizações de análise geradas 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 versus insertUI — Quando usar cada um

Escolha a ferramenta adequada de acordo com o caso de uso:

  • renderUI(): substitui reativamente todo o conteúdo de um espaço reservado. É melhor quando todo o bloco muda em conjunto.
  • insertUI(): adiciona novos elementos ao conteúdo existente. É melhor para listas que crescem e nas quais não se deseja renderizar tudo novamente.
  • updateXxxInput(): modifica uma entrada existente no próprio local. É melhor para alterar opções ou valores sem renderizar novamente.
  • conditionalPanel(): mostra ou oculta sem uma ida e volta ao servidor. É melhor para uma lógica simples de visibilidade.
# 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ção rápida

Qual é a principal diferença entre renderUI() e insertUI() ao criar uma interface dinâmica no Shiny?

Revisão da interface dinâmica

Principais aprendizados sobre interface dinâmica com renderUI e insertUI:

  • renderUI({}) + uiOutput('id'): substitui reativamente todo o conteúdo de um espaço reservado.
  • Retorne tagList() de renderUI() para renderizar vários elementos de uma só vez.
  • insertUI(selector, where, ui): insere elementos em qualquer local do DOM.
  • removeUI(selector): remove elementos por seletor CSS.
  • conditionalPanel(condition, ...): mostra ou oculta no cliente sem acessar o servidor.
  • updateSelectInput(), updateSliderInput(): modificam entradas existentes no próprio local.
  • Use sempre req(input$dynamic_id) para verificar se o valor não é NULL antes de as entradas dinâmicas serem renderizadas.
# 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]])
  })
}

Perguntas Frequentes

A aula “Interface dinâmica com renderUI e insertUI” é grátis?

Sim — o texto completo de “Interface dinâmica com renderUI e insertUI” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de R Academy, atualize para CoddyKit PRO. O curso de R Academy inclui 4 aulas no total.

O que vou aprender em “Interface dinâmica com renderUI e insertUI”?

Gere elementos da interface dinamicamente com base na entrada do usuário e no estado do servidor. Você pratica R Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar R Academy?

Nenhuma experiência prévia é necessária. R Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Interface dinâmica com renderUI e insertUI”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de R Academy?

Sim. Cada aula de R Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Aprofundamento em programação reativa
  2. Módulos Shiny para reutilização de código
  3. Interface dinâmica com renderUI e insertUI
  4. Implantando aplicativos Shiny
← Voltar para R Academy