renderUI と insertUI による動的 UI
ユーザー入力とサーバーの状態に応じて、UI 要素をその場で生成します。
「renderUI と insertUI による動的 UI」はCoddyKit上の無料R Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはR Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 R Academyコースには全4レッスンが含まれています。
動的UI — 理由と使いどき
アプリの起動時に必要なUIを完全には決定できない場合があります。ユーザーの選択、読み込んだデータ、実行時の条件に依存するためです。Shinyには2つの仕組みがあります。renderUI()はプレースホルダーの内容全体を置き換え、insertUI()/removeUI()はすべてを置き換えずに要素を追加または削除します。
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() と uiOutput()
サーバー内のrenderUI({...})は、リアクティブにUI要素を構築して返します。UI内のuiOutput('id')は、renderUIが生成した内容を表示するプレースホルダーを作成します。リアクティブな処理が再実行されるたびに、プレースホルダーの内容全体が置き換えられます。
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() を使う
renderUI()からtagList()を返すと、複数のUI要素を一度に描画できます。データに応じてコントロールの数が変わる場合の標準的なパターンです。たとえば、データセットの各列に1つずつフィルターを生成する場合に使います。
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() — 要素を動的に追加する
insertUI(selector, where, ui)は、ページ全体を再構築せずにDOMへUI要素を挿入します。挿入位置の指定にはCSSセレクターを使用します。whereには'afterEnd'、'beforeEnd'、'afterBegin'、'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() — 要素を削除する
removeUI(selector)は、CSSセレクターに一致する最初のDOM要素を削除します。すべての一致要素を削除するにはmultiple = TRUEを使用します。ユーザーが項目を追加・削除できるリスト型UIで、insertUI()と対になる機能です。
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() — クライアント側の表示制御
conditionalPanel(condition, ...)は、ブラウザーで評価されるJavaScript条件に基づいてUI要素を表示または非表示にします。renderUI()とは異なり、要素は常にDOM内に存在し、表示または非表示になるだけです。サーバーとの往復通信が不要なため、単純な表示・非表示の制御ではこちらの方が高速です。
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() — 既存の入力を変更する
入力コントロール全体を置き換える代わりに、updateSelectInput(session, id, choices, selected)を使うと、既存のselectInputの選択肢または選択値だけを更新できます。すべての入力タイプに同様の更新関数があり、updateSliderInput()、updateTextInput()などがあります。
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() と updateNumericInput()
更新関数はブラウザーにメッセージを送り、既存の入力の現在値、最小値、最大値、ラベルを変更します。renderUI()でコントロールを破棄して再作成するより効率的で、ページレイアウト内の位置も維持されます。
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))
)
})
}req() で renderUI の入力にアクセスする
renderUI()で動的に作成された入力は、描画されるまでNULLです。動的に作成された入力に依存するサーバーコードでは、初期化中のエラーを防ぐためにreq(input$dynamic_input)を使用します。
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]])
})
}appendTab() による動的なタブ
appendTab(inputId, tab, select)は、実行時にtabsetPanel()へ新しいタブを追加します。removeTab(inputId, target)はタブを1つ削除します。このパターンにより、ユーザーが動的に生成された分析ビューを開いたり、閉じたり、切り替えたりできるワークフローを実現できます。
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 と insertUI — どちらを使うか
用途に応じて適切なツールを選択してください:
- renderUI(): プレースホルダーの内容全体をリアクティブに置き換えます。ブロック全体が一緒に変化する場合に最適です。
- insertUI(): 既存の内容に新しい要素を追加します。すべてを再描画せずにリストを増やしたい場合に最適です。
- updateXxxInput(): 既存の入力をその場で変更します。再描画せずに選択肢や値を変更する場合に最適です。
- conditionalPanel(): サーバーとの往復通信なしで表示・非表示を切り替えます。単純な表示制御に最適です。
# 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)
}確認問題
Shinyで動的UIを構築する場合、renderUI()とinsertUI()の主な違いは何ですか。
動的UIのまとめ
renderUIとinsertUIによる動的UIの要点:
renderUI({}) + uiOutput('id'): プレースホルダーの内容全体をリアクティブに置き換えます。renderUI()からtagList()を返すと、複数の要素を一度に描画できます。insertUI(selector, where, ui): DOM内の任意の場所に要素を挿入します。removeUI(selector): CSSセレクターで要素を削除します。conditionalPanel(condition, ...): サーバーを介さずにクライアント側で表示・非表示を切り替えます。updateSelectInput()、updateSliderInput(): 既存の入力をその場で変更します。- 動的な入力が描画される前の
NULLに備えて、必ずreq(input$dynamic_id)を使用してください。
# 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]])
})
}AI チューターと学ぶ R — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 43
- レッスン
- 159
よくある質問
「renderUI と insertUI による動的 UI」レッスンは無料ですか?
はい。「renderUI と insertUI による動的 UI」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、R Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 R Academyコースには全4レッスンが含まれています。
「renderUI と insertUI による動的 UI」で何を学びますか?
ユーザー入力とサーバーの状態に応じて、UI 要素をその場で生成します。 ブラウザで直接実行するハンズオンコードでR Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
R Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのR Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「renderUI と insertUI による動的 UI」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このR Academyレッスンでコードを書いて実行できますか?
はい。すべてのR Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- リアクティブプログラミングの深掘り
- コード再利用のための Shiny モジュール
- renderUI と insertUI による動的 UI
- Shiny アプリをデプロイする