2017-08-24 13 views
0

これは以前のクエリ[Creating asymmetric layouts involving rows and column in Shinyの拡張です。私は動的なUI出力を作成しようとしています。各トピックごとにドロップダウンメニューとテキストボックスをグループ化してレイアウトを修正するための提案や、動的に作成されたさまざまなドロップダウンやテキストボックスからデータを取り込む方法についても提案が必要です。RShinyの動的フォーム

これは、以前のクエリ[How to add/remove input fields dynamically by a button in shinyから変更されたコードである:あなたのレイアウトの問題を解決するための

library(shiny) 

ui <- shinyUI(fluidPage(
sidebarPanel(
actionButton("add_btn", "Add Textbox"), 
actionButton("rm_btn", "Remove Textbox"), 
textOutput("counter") 
), 
mainPanel(
    fluidRow(column(6,uiOutput("selectbox_ui"), offset = 0), 
column(6,fluidRow(column(6,uiOutput("textbox_ui1"), uiOutput("textbox_ui2"))), 
    fluidRow(column(6,uiOutput("textbox_ui3"), uiOutput("textbox_ui4"),offset = 0)), offset = 0) 
) 
))) 

server <- shinyServer(function(input, output, session) { session$onSessionEnded(stopApp) 

# Track the number of input boxes to render 
counter <- reactiveValues(n = 0) 

observeEvent(input$add_btn, {counter$n <- counter$n + 1}) 
observeEvent(input$rm_btn, {if (counter$n > 0) counter$n <- counter$n - 1}) 

output$counter <- renderPrint(print(counter$n)) 

textboxes1 <- reactive({n <- counter$n 
if (n > 0) 
    {lapply(seq_len(n), function(i) {textInput(inputId = paste0("textin1", i),label = paste0("Textbox_A_Topic", i), value = "Hello World!")})} 
}) 

textboxes2 <- reactive({n <- counter$n 
    if (n > 0) 
    {lapply(seq_len(n), function(i) {textInput(inputId = paste0("textin2", i),label = paste0("Textbox_B_Topic", i), value = "Hello World!")} )} 
}) 
textboxes3 <- reactive({n <- counter$n 
    if (n > 0) 
    {lapply(seq_len(n), function(i) {textInput(inputId = paste0("textin3", i),label = paste0("Textbox_C_Topic", i), value = "Hello World!")} )} 
}) 
textboxes4 <- reactive({n <- counter$n 
    if (n > 0) 
    {lapply(seq_len(n), function(i) {textInput(inputId = paste0("textin4", i),label = paste0("Textbox_D_Topic", i), value = "Hello World!")} )} 
}) 
selectboxes <- reactive({n <- counter$n 
    if (n > 0) 
    {lapply(seq_len(n), function(i) {selectInput(inputId = paste0("selectTopic", i), label = paste0("Topic", i), 
               choices = c("one", "two", "three"), selected = "two", multiple = FALSE)})} 
}) 

output$textbox_ui1 <- renderUI(textboxes1()) 
output$textbox_ui2 <- renderUI({textboxes2() }) 
output$textbox_ui3 <- renderUI({textboxes3() }) 
output$textbox_ui4 <- renderUI({textboxes4() }) 
output$selectbox_ui <- renderUI({selectboxes()}) 

}) 

答えて

1

、それは単一のトピックに関連するすべての要素(つまり、ドロップダウンメニューと考えるのに役立ちます4つのテキスト入力)を1つの要素ブロックとして構成します。次に、これらのブロックの1つを作成する方法を見つけてください(おそらく、プロセスを関数に抽出することをお勧めします)。ブロックを積み重ねて、目的の結果を達成してください。あなたの例では、完全なトピックブロックを作成するための

関数は次のようなものになります:

topic_ui <- function(i) { 

    # render all elements related to a single topic into one div 

    fluidRow(

    # drop-down select menu on the left 
    column(width = 6, offset = 0, 
     selectInput(
     inputId = paste0("selectTopic", i), 
     label = paste0("Topic", i), 
     choices = c("one", "two", "three"), 
     selected = "two", 
     multiple = FALSE 
    ) 
    ), 

    # text boxes on the right 
    column(width = 6, offset = 0, 
     lapply(LETTERS[1:4], function(l) { 
     textInput(
      inputId = paste0("textin", l, i), 
      label = paste0("Textbox_", l, "_Topic", i), 
      value = "Hello World!" 
     ) 
     }) 
    ) 

) 

} 

を今では、新しいトピックのUIクリエイター機能で動作するようにサーバーを変更するの問題です:

server <- shinyServer(function(input, output, session) { 

    session$onSessionEnded(stopApp) 

    # Track the number of input boxes to render 
    counter <- reactiveValues(n = 0) 

    observeEvent(input$add_btn, { 
    counter$n <- counter$n + 1 
    }) 

    observeEvent(input$rm_btn, { 
    if (counter$n > 0) 
     counter$n <- counter$n - 1 
    }) 

    output$counter <- renderPrint(print(counter$n)) 

    # render a number of topic ui elements based on the counter, 
    # each consisting of a selectInput and four textInputs 
    topics <- reactive({ 
    n <- counter$n 
    if (n > 0) 
     lapply(seq_len(n), topic_ui) 
    }) 

    output$topic_ui <- renderUI(topics()) 

}) 

そして最後に、UI側も、結果として簡素化することができます。

ui <- shinyUI(fluidPage(

    sidebarPanel(

    actionButton("add_btn", "Add Textbox"), 
    actionButton("rm_btn", "Remove Textbox"), 
    textOutput("counter") 

), 

    mainPanel(

    # dynamically created ui elements 

    uiOutput("topic_ui") 

) 

)) 

ダイナミック要素からの入力をキャプチャする場合、基本的に静的な入力要素と同じ方法で行います:inputId引数で指定された名前を参照してください。合併症として、動的要素が最初に存在するかどうかを確認するためにいくつかのチェックを含める必要があると思います。ダイナミックな入力をしたいと思っているものを含めるようにサンプルケースを拡張すると、もう一度見てみることができます!

+0

私が今直面している問題は、テキストボックスを入力した後、追加ボタンをクリックしてデータを追加すると、入力された値を 'Hello world'値で置き換えた新しいテキストボックスが作成されますテキストボックス。 – RanonKahn

+0

私はそれを回避するには2つの方法が考えられます:すべての入力要素の現在の状態をリアクティブリストに保存し、それらの状態を使用してボックスを追加または削除するときに古い入力を再作成します(https: //stackoverflow.com/a/31457114/4550695);またはトピックの量が最大であれば、それらを一度にすべて作成し、実際にそれらを追加および削除するのではなく、 'shinyjs'を使用してカウンター値に応じて動的に表示および非表示にします。 –

+0

私は2番目のオプションを使用します。 – RanonKahn