このエントリでは、rstudio::conf 2017で紹介されたShinyのinsertUI
を解説します。
https://github.com/bborgesr/rstudio-conf2017
githubで公開されたソースコードを引用しています。
Shinyアプリケーションでは、予めui.R、または (app.R中の) uiオブジェクトとして、固定のUIを配置する必要があります。
動的なUIでは、入力に応じて表示されるUIコンポーネントの種類が変わります。Shinyで動的なUIを実現するための方法の一つがrenderUI
です。
renderUIの使用例
「01-renderUI.R」はrenderUI
の使用例です。ユーザの入力により、renderUI
で動的なUIを表示します。
実行例
runApp
でアプリケーションを実行すると、初期状態で、選択されたdatasetのsummaryが表示されています。
plot, headを選択すると、summaryが表示されていたUIコンポーネントのあったメインパネルに、plotとheadが表示されます。
ソースコード
renderUI
の使用例のコードを以下に示します。
library(shiny) library(datasets) shinyApp( ui = fluidPage( titlePanel('Using renderUI'), sidebarLayout( sidebarPanel( selectInput('data', 'Choose a dataset', c('rock', 'pressure', 'cars')), radioButtons('tool', 'Choose a tool', c('summary', 'plot', 'head')) ), mainPanel( uiOutput('result') ) ) ), server = function(input, output, session) { dataset <- reactive({ switch(input$data, 'rock' = rock, 'pressure' = pressure, 'cars' = cars) }) output$result <- renderUI({ switch(input$tool, 'summary' = verbatimTextOutput('summary'), 'plot' = plotOutput('plot'), 'head' = tableOutput('head')) }) output$summary <- renderPrint({ summary(dataset()) }) output$plot <- renderPlot({ plot(dataset()) }) output$head <- renderTable({ head(dataset()) }) } )
ui側での定義
ui側でrenderUI
を用いるためには、uiOutput(id)
でコンポーネントを定義します。
使用例では、メインパネル中に宣言があります。
uiOutput('result')
server側でresultで定義されたuiコンポーネントを表示します。
server側での定義
server側では、renderUI
で、以下のいずれかの方法で出力を返します。
output[[id]] <- renderUI({ ... }
output[[id]] <- renderUI({ tagList(...) })
使用例では、switch
文を用いて、
output$result <- renderUI({ switch(input$tool, 'summary' = verbatimTextOutput('summary'), 'plot' = plotOutput('plot'), 'head' = tableOutput('head')) })
ユーザの入力に対応して、verbatimTextOutput
, plotOutput
, tableOutput
のいずれかを出力に指定します。
出力として定義したsummary, plot, headはそれぞれ対応するrender関数によるオブジェクトの定義が必要です。
output$summary <- renderPrint({ summary(dataset()) }) output$plot <- renderPlot({ plot(dataset()) }) output$head <- renderTable({ head(dataset()) })
まとめ
renderUIを用いて、ui中にuiOutputで指定したコンポーネントを動的に表示することができます。
ui側で
uiOutput
によるコンポーネントの定義、server側でrenderUI
を用いて入力に応じて動的に表示するコンポーネントを変えます。表示するコンポーネントを変えるだけでなく、新たにコンポーネントを追加表示する場合には、uiOutputで確保したスロットに再度renderによる表示が必要となります。これを回避して、より動的にコンポーネントの追加表示を行うのに使用するのが
insertUI
です。