Lit components for shiny, with a twist.
Currently implemented inputs:
litActionButton
litActionLink
litCheckboxesInput
litColorInput
litDatalistInput
litFilterInput
litPasswordInput
litTextInput
litTextAreaInput
litRadioInput
litSwitchInput
litTextLabelInput
litTogglerInput
litRangeInput
litSelectInput
litSelectizeInput
- Only works with bslib's Bootstrap 5.
- These inputs are not captured by Shiny's bookmarking session
- These inputs are not captured by shinytest2
These limitations are unlikely to be lifted in the future.
You can install the development version of litter from GitHub with:
# install.packages("remotes")
remotes::install_github("devOpifex/litter")
{litter} allows using multiple inputs with a single observer.
library(shiny)
library(litter)
ui <- fluidPage(
theme = bslib::bs_theme(5L),
litActionButton(
name = "btn",
"Button #1"
),
litActionButton(
name = "btn",
"Button #2"
)
)
server <- function(input, output, session){
observeEvent(input$btn, {
print(input$btn)
})
}
shinyApp(ui, server)
- All input functions start in
lit
. - All inputs have a
value
(even if it can be a vector of multiple values) - All inputs can be updated with
update_input
- All inputs accept a
callback
argument (Javascript function) - Labels are not part of the input
- All inputs accept a
send_on_render
argument - All inputs return data in the same format:
list(
props = list(),
id = "", # omitted if not set
value = 1L
)
Whilst inputs that share name
trigger the same input it can be difficult to
distinguish between inputs.
For this you can pass any "prop" to the three dot construct ...
.
For example, the application below will return the values set to myProp
to input$btn
.
library(shiny)
library(litter)
ui <- fluidPage(
theme = bslib::bs_theme(5L),
litActionButton(
name = "btn",
"Button #1",
myProp = "A"
),
litActionButton(
name = "btn",
"Button #2",
myProp = "B"
)
)
server <- function(input, output, session){
observeEvent(input$btn, {
print(input$btn)
})
}
shinyApp(ui, server)
You can pass a JavaScript callback function, in which case it is called instead of sending the value to the shiny server.
library(shiny)
library(litter)
ui <- fluidPage(
theme = bslib::bs_theme(5L),
litActionButton(
callback = "() => {alert('Hello!')}"
)
)
server <- function(...){}
shinyApp(ui, server)
All inputs can be updated with update_input
.
library(shiny)
library(litter)
ui <- fluidPage(
theme = bslib::bs_theme(5L),
span("Type", tags$code("error"), "below"),
litTextInput(
name = "txt"
)
)
server <- function(input, output){
observeEvent(input$txt, {
if(input$txt$value == ""){
update_input(name = "txt", class = "")
return()
}
if(input$txt$value == "error"){
update_input(name = "txt", class = "is-invalid")
return()
}
update_input(name = "txt", class = "is-valid")
})
}
shinyApp(ui, server)
An example of generating inputs with {litter}.
library(shiny)
library(litter)
ui <- fluidPage(
theme = bslib::bs_theme(5L),
litRangeInput(
"n",
value = 5,
min = 3,
max = 10
),
uiOutput("created"),
verbatimTextOutput("result")
)
server <- function(input, output, session) {
output$created <- renderUI({
# we create n input
lapply(seq(input$n$value), \(x){
div(
class = "mb-1",
span("Input", x),
# all inputs have the same name
litTextInput(
name = "text",
n = x,
send_on_render = FALSE
)
)
})
})
output$result <- renderPrint({
print(input$text)
})
}
shinyApp(ui, server, options = list(port = 3000L))
All styling is taken from bslib's set theme as well as the class
argument of
all inputs.