I am trying to create simple webapp where I want to take in multiline input from user using HTML textarea control. Is there any out of the box way of creating such an input
You can add a textarea using tags
and it should be picked up by Shiny automatically:
tags$textarea(id="foo", rows=3, cols=40, "Default value")
Or if you're more comfortable with straight HTML you can also do
HTML('<textarea id="foo" rows="3" cols="40">Default value</textarea>')
In either case, input$foo
should reflect the textarea's value.
From version 0.14 shiny has an implementation of textAreaInput.
For benefit of others, I will post how I solved the problem using custom UI control following Shiny tutorial
Firstly, I crearted textarea.js file as follows
$(document).on("click", "textarea.inputTextarea", function(evt) {
// evt.target is the button that was clicked
var el = $(evt.target);
// Raise an event to signal that the value changed
el.trigger("change");
});
var inputTextareaBinding = new Shiny.InputBinding();
$.extend(inputTextareaBinding, {
find: function(scope) {
return $(scope).find(".inputTextarea");
},
getValue: function(el) {
return $(el).text();
},
setValue: function(el, value) {
$(el).text(value);
},
subscribe: function(el, callback) {
$(el).on("change.inputTextareaBinding", function(e) {
callback();
});
},
unsubscribe: function(el) {
$(el).off(".inputTextareaBinding");
}
});
Shiny.inputBindings.register(inputTextareaBinding);
Then I added following function in ui.R of shiny webapp before shinyUI() is called
inputTextarea <- function(inputId, value="", nrows, ncols) {
tagList(
singleton(tags$head(tags$script(src = "textarea.js"))),
tags$textarea(id = inputId,
class = "inputtextarea",
rows = nrows,
cols = ncols,
as.character(value))
)
}
Then I used above defined function to create the desired textarea control element in ui.R
shinyUI(pageWithSidebar(
# Application title
headerPanel("Test Header Panel"),
sidebarPanel(),
mainPanel(
inputTextarea('exampleTextarea', '',20,35 )
)
))
Building off of Joe's answer (https://stackoverflow.com/a/14452837/5776618), you can also nest tags into your own function to achieve the same output as the standard Shiny built-in input functions.
textareaInput <- function(id, label, value, rows=20, cols=35, class="form-control"){
tags$div(
class="form-group shiny-input-container",
tags$label('for'=id,label),
tags$textarea(id=id,class=class,rows=rows,cols=cols,value))
}
This is a way to avoid writing the JS code (if you want to) while still...
Using the function is same as if you are using the built-in or if you built a custom UI.
textareaInput("textareaID","Text Area Label", "Insert text here...", rows = 20, cols = 35)
May or may not be relevant here, but I made the shinyAce package to wrap up and expose the Ace text editor in Shiny. Ace is primarily used for code editing (complete with syntax highlighting for a variety of languages), but provides a text-area-like interface for writing composing multi-line text/code.
You can check out the example to see if that might be what you're looking for. (Try different "modes" for syntax highlighting and themes for color combinations.)
Here's a quick solution that preserves the shiny input feel, but allows custom number of columns:
textareaInput <- function(inputID, label, value="", rows=10, columns=80) {
HTML(paste0('<div class="form-group shiny-input-container">
<label for="', inputID, '">', label,'</label>
<textarea id="', inputID, '" rows="', rows,'" cols="',
columns,'">', value, '</textarea></div>'))
}
In your ui.R
script, you can add:
textareaInput("shazam", "My text box")
Note: To get a Bootstrap feel to the textarea, you can use:
textareaInput <- function(inputID, label, value="", rows=10) {
HTML(paste0('<div class="form-group shiny-input-container">
<label for="', inputID, '">', label,'</label>
<textarea class="form-control" id="', inputID,
'" rows="', rows, '">', value, '</textarea></div>'))
}