shinyFeedback Introduction

Functionality

The shinyFeedback package displays user friendly messages that appear alongside shiny inputs. e.g.

shinyFeedback currently works with the following shiny and shinyWidgets inputs:

  • shiny::dateInput()
  • shiny::dateRangeInput()
  • shiny::fileInput()
  • shiny::numericInput()
  • shiny::passwordInput()
  • shiny::selectInput()
  • shiny::sliderInput()
  • shiny::textAreaInput()
  • shiny::textInput()
  • shinyWidgets::airDatepickerInput()
  • shinyWidgets::pickerInput()

Setup

In order to use shinyFeedback you need to include the useShinyFeedback() function at the top of your UI.

The following is a minimal example of a shiny app that uses shinyFeedback. Run the following code in your R console to run the app.

library(shiny)
library(shinyFeedback)

ui <- fluidPage(
  useShinyFeedback(), # include shinyFeedback
  
  textInput(
    "myInput",
    "Warn if >3 characters",
    value = ""
  )
)

server <- function(input, output, session) {
  observeEvent(input$myInput, {
    
    if (nchar(input$myInput) > 3) {
      showFeedbackWarning(
        inputId = "myInput",
        text = "too many chars"
      )  
    } else {
      hideFeedback("myInput")
    }
    
  })
}

shinyApp(ui, server)

The above app has one textInput() input in the UI. In the server function, we write the code to conditionally display a feedback message. If the text input has more than 3 characters, the feedback message is displayed.

feedback()

The feedback() function is an alternative to using showFeedback() and hideFeedback(). With feedback() the feedback message is shown/hidden based on whether the show argument to feedback() is “truthy”. “truthiness” is determined by shiny::isTruthy(). feedback() works nicely with reactive expressions that use shiny::req() to check the validity of Shiny inputs. e.g.

library(shiny)
library(shinyFeedback)

ui <- fluidPage(
  useShinyFeedback(), # include shinyFeedback
  
  selectInput(
    "dataset",
    "Dataset",
    choices = c(
      "airquality",
      "Unknown dataset"
    )
  ),
  
  tableOutput('data_table')
)

server <- function(input, output, session) {
  
  data_out <- reactive({
    req(input$dataset)
    
    dataset_exists <- exists(input$dataset, "package:datasets")
    feedbackWarning("dataset", !dataset_exists, "Unknown dataset")
    req(dataset_exists, cancelOutput = TRUE)

    get(input$dataset, "package:datasets")
  })
  
  output$data_table <- renderTable({
    head(data_out())
  })
}

shinyApp(ui, server)

Usage Inside Shiny Modules

shinyFeedback works inside shiny modules.

As for all modules, input and output IDs in the module UI code must be wrapped in shiny::ns() calls. Inside your module server code, you need not wrap input or output IDs inside shiny::ns(); shinyFeedback will automatically prepend the namespace of your current module.

Here is a simple example using shinyFeedback inside a module:

library(shiny)
library(shinyFeedback)

numberInput <- function(id) {
  ns <- NS(id)
  tagList(
    useShinyFeedback(),
    numericInput(
      ns("warningInput"),
      "Warn if Negative",
      value = 0
    )
  )
}

number <- function(input, output, session) {
  observeEvent(input$warningInput, {
    req(input$warningInput)
    if (input$warningInput < 0) {
      showFeedbackWarning(inputId = "warningInput")
    } else {
      hideFeedback("warningInput")
    }
  })
}

ui <- fluidPage(
  numberInput(id = "numberFoo")
)

server <- function(input, output) {
  callModule(module = number, id = "numberFoo")
}

shinyApp(ui, server)