2

I need to be able to add textInput() side by side in a shiny application. There should be a textInput() which takes the lable of the new text box and command button, where every time command button clicked, a new textbox should be added to the list where label should be taken from the first txtInput.

for example:

1stTextBox:[   Application   ]
{commandButton}

when I click the commandButton, I should have a textInput like this below the commandButton,

Application:[      ]

if I put something else to 1stTextBox and click the command button, it should be added to textInput list.

Any ideas how could do this in shiny dynamically?

This is the error:

Listening on http://127.0.0.1:3091
Warning: Error in handlers$add: Key / already in use
Stack trace (innermost first):
    43: handlers$add
    42: handlerManager$addHandler
    41: startApp
    40: runApp
     1: shiny::runApp
Error in handlers$add(handler, key, tail) : Key / already in use
user1471980
  • 10,127
  • 48
  • 136
  • 235
  • You need a combination of `observeEvent` and `renderUI` in your server code. `observeEvent` would watch for the button click, then use `renderUI` to draw a second text input with the specified label. – Xiongbing Jin Mar 22 '16 at 17:35
  • @warmoverflow, I am very new to shiny. do you have any examples? – user1471980 Mar 22 '16 at 17:41
  • Here is an example that I made for another question. It observes changes in a numericInput and renders more numericInput. http://stackoverflow.com/questions/36094718/r-shiny-dynamic-input/36096128#36096128 – Xiongbing Jin Mar 22 '16 at 17:44

1 Answers1

2

I give an example code. To try this, copy the scripts and run the whole.

I am using reactiveValues object to keep the information at the back end. Here, info_keeper$input_info is a list, where each element is supposed to be a 3-length character vector of [id, label, value].

When the button is clicked, it (1) the contents of textInputs already defined are stored; (2) new element is added.

I am using isolate perhaps more than necessary, to avoid unwanted behavior.

library(shiny)

ui <- list(
  textInput("name", "Type new text input name", value = ""),
  actionButton("btn", "click me to create text input"),
  uiOutput("newInputs")
)

server <- function(input, output)
{
  info_keeper <- reactiveValues(
    input_info = list()
  )

  observeEvent(input$btn, {
    # copy the current contents to info_keeper
    isolate(
    {
      for (i in seq_along(info_keeper$input_info))
      {
        id <- info_keeper$input_info[[i]][1]
        info_keeper$input_info[[i]][3] <- input[[id]]
      }
    })

    # add new text input to the info_keeper
    isolate(
    {
      newid <- paste(
        "text", isolate(length(info_keeper$input_info)) + 1, sep = "")
      info_keeper$input_info <- c(
        info_keeper$input_info, list(c(newid, input$name, "")))
    })

    # invoke the update of the text inputs
    info_keeper
  })

  output$newInputs <- renderUI({
    lapply(info_keeper$input_info, function(a)
      textInput(a[1], a[2], value = a[3]))
  })
}

runApp(list(ui = ui, server = server))
Kota Mori
  • 6,510
  • 1
  • 21
  • 25
  • I keep getting this error "ERROR: Key / already in use". I placed the whole code in rstudio window. Any ideas? – user1471980 Mar 22 '16 at 18:19
  • I don't know. Just for checking, can you restart rstudio, paste the whole code in the editor, then click the source button of the rstudio? In my environment, this starts the app with no error. If this still causes the same error, let me know. – Kota Mori Mar 23 '16 at 00:01
  • yes, it worked. quick question. I need to be able to use the values in the text boxes to make some calculations. 1) how do I ensure values goes in the text boxes are numeric? 2) how would I know the id of the textboxes and retrieve values from each text box. Each text box would be different, for example. first one would be number of web servers. Is there a way to track the id of these dynamically generated text boxes and their values? – user1471980 Mar 23 '16 at 13:28
  • 1
    1) Since the values of textInput is a character, you will need to check if the character represents a number. For example, to check if a character consists only of digits, `regexpr("^[0-9]+$", text)`. 2) In my code, the id of textboxes are stored in `info_keeper$input_info`. Each element is a character vector of [ID, label, value] and corresponds to the text box in the order of creation. Since IDs are automatically named in the code, you may want to use the label for finding a certain textbox. – Kota Mori Mar 23 '16 at 13:42
  • I accepted your answer which answered my original question. I have some more questions, I am not really following your code. Should I ask a new question? The purpose of this to have some input textboxes, get data from the user, make some calculations and output the results per inputtext box. Let's say, 1st input text box is webserver, after calculations are done, I need to print out the output webserver. Need to do this for each input text boxes, so I need to know which text boxes are which and what users put in them. Does this make sense? – user1471980 Mar 23 '16 at 14:43
  • I am more than happy to answer your question but this is a lot. Can you open a new question and let me know the link to it? I will get notified when you add a comment here. In the new question, please specify what you want to do more precisely. I am not sure what you mean by "get data from the user", "1st text boxes is webserver", "print out the output webserver". Also if you provide your code that at least creates the initial configuration of the app, then you have a better chance to get the answer you are looking for. – Kota Mori Mar 23 '16 at 15:30
  • Mori, I've created another question. Hopefully, it will make sense. Basically I need to take data inserted into the textboxes, make some calculations and show the data next to each textboxes. Here is the question: http://stackoverflow.com/questions/36183246/how-do-you-calculate-data-taken-from-textinput-boxes-in-shiny – user1471980 Mar 23 '16 at 16:12
  • any ideas about the new post? – user1471980 Mar 23 '16 at 19:13