1

I am trying to create a shiny user interface with a dynamic reactive UI.

Essentially a user has to input the number of variants for an experiment (1-10).

For each variant the user is required to enter the variant name in a textbox and also a proportion 1 - 100 to allocate to each variant. The sum of proportions across all variants should add to 100.

e.g. User selects 5 variants. Then for each variant 1-5 the user should get dropdowns to select proportions.

  • Variant 1 proportion (1-100), user selects 40 say
  • Variant 2 proportion (1-60), user selects 10 say
  • Variant 3 proportion (1-50), user selects 35 say
  • Variant 4 proportion (1-15), user selects 10 say
  • Variant 5 proportion (5), user has no say in allocating this - the proportion is backed out as 100 - (v1 + v2 + v3 + v4) = 5

I have borrowed code from here to start this: Producing dynamic/multiple input boxes to collect data depending on user selection in Shiny R

ui.R

library(shiny)

shinyUI(pageWithSidebar (

  headerPanel( "Portfolio Returns"),

  sidebarPanel(
    numericInput("assets", label = "Enter Number of variants in Experiment", value="1"),
    uiOutput("variants")
  ),
  mainPanel()
))

Server.R

library(shiny)

shinyServer( function(input, output, session) {

  output$variants <- renderUI({
    numAssets <- as.integer(input$assets)

    lapply(1:numAssets, function(i) {
      list(tags$p(tags$u(h4(paste0("Variant ", i, ":")))),
           textInput(paste0("variant", i), label = "Variant Name", value = paste0("Variant ", i, " name..."))
           , numericInput(paste0("weight", i)
                          , label = "Proportion allocated (0 - 100)", value=0))
    })
  })
})

Could anyone please assist with the above?

Community
  • 1
  • 1
user4687531
  • 1,021
  • 15
  • 30

1 Answers1

3

I believe that the solution is to have the final numeric input mimic a numeric input, but actually just be a calculated output. Instead of creating as many numeric inputs as numAssets, create 1 less. Then create another output that looks like the rest, but whose value is calculated rather than entered. The code below does that, generally speaking, but does not do a good job of mimicking the appearance of the other numeric inputs. This code can also be pulled from github.

ui.R

library(shiny)
shinyUI(pageWithSidebar (
  headerPanel( "Portfolio Returns"),
  sidebarPanel(
    numericInput("assets", label = "Enter Number of variants in Experiment", value="3")
  ),
  mainPanel(
    uiOutput("variants"),
    uiOutput("lastVariant"))
))

server.R

library(shiny)
shinyServer( function(input, output, session) {
  output$variants <- renderUI({
    numAssets <- as.integer(input$assets)  
      lapply(1:(numAssets-1), function(i) {
        list(tags$p(tags$u(h4(paste0("Variant ", i, ":")))),
             textInput(paste0("variant", i), label = "Variant Name", value = paste0("Variant ", i, " name..."))
             , numericInput(paste0("weight", i)
                            , label = "Proportion allocated (0 - 100)", value=0)
        )
      }) #end of lapply
  }) # end of renderUI
  
  output$lastVariant <- renderUI({
    numAssets <- as.integer(input$assets)
    for (j in 1:(numAssets-1)){
      if(j==1){x=100}
      x = x - input[[paste0("weight",j)]]
    }
    tagList(
      tags$p(tags$u(h4(paste0("Variant ", numAssets, ":")))),
      textInput(paste0("variantFinal"), label = "Variant Name", value = paste0("Variant ", numAssets, " name...")), 
      tags$p(tags$b("Proportion allocated (0 - 100)")),
      helpText(paste0(x))
    ) #end of tagList
  }) #end of renderUI
}) #end of shinyServer
Community
  • 1
  • 1
Paul de Barros
  • 1,170
  • 8
  • 22
  • Great answer! Marked as accepted. Two (hopefully) small follow up questions: – user4687531 Apr 09 '15 at 04:07
  • Paul is there a way to make the proportion selected a dropdown of 0-100 rather than as textInput? – user4687531 Apr 09 '15 at 05:03
  • Sure. instead of `numericInput`, use `selectInput`, and set the choices to `c(0:100)`. Then you'll have to use as.`as.integer` on the returned value (since it will return characters). http://shiny.rstudio.com/reference/shiny/latest/selectInput.html http://shiny.rstudio.com/gallery/widget-gallery.html – Paul de Barros Apr 09 '15 at 11:55
  • Thanks again Paul - appreciate it. – user4687531 Apr 10 '15 at 01:38