mosk915
mosk915

Reputation: 814

Add character limit to a text box in an R shiny app

I have a shiny app with a text input box. I want to limit the number of characters that can be entered and display a note below the box saying how many characters remain. I'm not sure how I would prevent more characters than the limit from being entered. The code I have below, if it worked, would only display how many characters remain but there's nothing stopping it from being negative.

As a less preferable solution, I was trying to have a modal box pop up if the action button is clicked and the input box has more than the character limit, but I couldn't get that to work either.

ui <- fluidPage(title = "App Title",
                dashboardPage(title = "App Title",
                              dashboardBody(tabItems(tabItem(tabName = 'Tab1',
                                                             fluidRow(uiOutput('comment_UI'),
                                                                      actionButton('upload_comment', 'Upload Comment')
                                                                     ),
                                                             helpText(paste0('Characters remaining:', textOutput('charcount')))
                                                            )
                                                    )
                                            )
                              )
               )

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

                output$comment_UI <- renderUI({textareaInput('comment','Comment')})

                output$charcount <- renderText({800-nchar(input$comment)})

                observeEvent(input$upload_comment, { 
                                 if(nchar(input$comment) <= 800) {
                                      [do stuff] }
                                 else {
                                      showModal(modalDialog(title = "Error",
                                                            "The character limit has been exceeded.")) }
                                                   }                  
                                           }

Upvotes: 3

Views: 2821

Answers (2)

Samuel Calderon
Samuel Calderon

Reputation: 741

Since {htmltools} v0.5.2 it is possible to use tagQuery() and its methods to modify HTML before rendering.

Here I provide an example of a wrapper of textInput() that allows to set the maxlength attribute.

textInput2 <- function(inputId, label, value = "", width = NULL, 
                       placeholder = NULL, maxlength = NULL) {
    
    tag <- shiny::textInput(
        inputId = inputId,
        label = label,
        value = value,
        width = width,
        placeholder = placeholder
    )
    
    if (!is.null(maxlength)) {
        htmltools::tagQuery(tag)$
            children("input")$
            addAttrs(maxlength=maxlength)$
            allTags()
    } else {
        tag
    }
    
}

This attribute has some constrains you should be aware of. Also, feedback to users (e.g. showing that the user is reching the chr limit) needs to be handled in javascript.

If you want to make some reactive updates you can use updateTextInput() normally.

Upvotes: 0

Florian
Florian

Reputation: 25435

I created a solution without javascript below, but it is actually much simpler; as always, the shinyjs package can simplify things greatly: How to limit the number of characters accepted by textInput in Shiny app. In your case. add shinyjs::runjs("$('#mytext').attr('maxlength',8)") to your server. Please note that you should put the line library(shinyjs) and useShinyjs() in your ui for this to work.


Here is a possible solution which uses an observeEvent like you did in your solution. Any time the used exceeds the character limit, the input is reset by the observer to the maximum character limit, and a modal dialog pops up, informing the user of the mistake.

Note that the user can still type 15 characters if he types quickly. I think a better solution can be attained with some custom javascript, but I am not an expert in that. Hope this helps!

library(shiny)    

ui <- fluidPage(title = "App Title",
                textInput("mytext","Input text:"),
                textOutput('helptext')
)

max_char = 10

server <- function(input, output, session) 
{
  output$helptext <- reactive({ paste0('only ', max_char-nchar(input$mytext), ' characters remaining.' ) })

  observeEvent(input$mytext,{
    if(nchar(input$mytext)>max_char)
    {
      updateTextInput(session,'mytext',value=substr(input$mytext,1,max_char))
      showModal(modalDialog(
        title = "Error!",
        "Character limit exceeded!",
        easyClose = TRUE
      ))
    }
  }
  )

}
shinyApp(ui,server)

Upvotes: 4

Related Questions