library(shiny)
ui <- fluidPage(
sliderInput("obs", "Number of observations", 0, 1000, 500),
actionButton("goButton", "Go!", class = "btn-success"),
plotOutput("distPlot")
)
server <- function(input, output) {
output$distPlot <- renderPlot({
input$goButton
dist <- isolate(rnorm(input$obs))
hist(dist)
})
}
shinyApp(ui, server)
bslib
bslib is a package that makes bootstrap’s css available for use in R. The exact original description is Tools for theming Shiny and R Markdown via Bootstrap 3, 4, or 5. It allows you to utilize multiple themes in Shiny and Rmarkdown (including Quarto, naturally).
In this article, we’ll focus on Shiny as an example of how bslib can be utilized. In fact, Shiny uses bootstrap for its design by default. However, Shiny is known for its feature-oriented updates, as it has become a very heavy package with a lot of components and relationships that are affected by updates.This means that the bootstrap part, which mainly deals with the UI, is using version 3.4.1, which is 5 years old, and it defaults to a distinctive blue/gray theme unless you set a separate theme (the latest version is 5.3.3).
So in order to update the stagnant UI, shiny creates a separate R package that deals with the UI and overwrites it to provide the latest bootstrap features.
This article does not cover the main uses of bslib.
shiny with loading
There have been several ways to solve this issue with actionButton
:
- Using a progress indicator
is a way to utilize the Progress Indicator UI provided by shiny natively, which allows you to show the user the progress as the process/step of the operation progresses.
server <- function(input, output) {
output$plot <- renderPlot({
input$goPlot
dat <- data.frame(x = numeric(0), y = numeric(0))
withProgress(message = 'Making plot', value = 0, {
n <- 10
for (i in 1:n) {
dat <- rbind(dat, data.frame(x = rnorm(1), y = rnorm(1)))
incProgress(1/n, detail = paste("Doing part", i))
Sys.sleep(0.1)
}
})
plot(dat$x, dat$y)
})
}
ui <- shinyUI(basicPage(
plotOutput('plot', width = "300px", height = "300px"),
actionButton('goPlot', 'Go plot')
))
shinyApp(ui = ui, server = server)
However, this has the disadvantage that functions and objects such as withProgress
, incProgress
, or Progress
require extra code for time-consuming operations.
- Use separate R packages
In R’s ecosystem, it’s safe to assume that there are many problems to solve, and each problem has its own R package. The same is true for the ability to display the long gap between an actionButton and the result of an operation in the UI.
Similar to the progress indicator before, think of it as a custom feature that needs to be solved by writing additional code and allows for a little more design or customization.
Here are some example packages and examples (in alphabetical order)
Summary
In this post, we introduced the newest feature in bslib, input_task_button, and a simple use case.
This is a feature that potentially improves the user experience, and I think it solves a problem that traditionally requires additional code to be written in shiny.
In particular, unlike other web applications, Shiny often takes a long time due to large data operations, but it has a relatively poor UI/UX, so replacing the existing actionButton
with input_task_button
will go a long way to compensate for this.
I hope you found this article helpful, and I’ll see you in the next installment!
Reuse
Citation
@online{kim2024,
author = {Kim, Jinhwan},
title = {Bslib: Input\_task\_button {소개}},
date = {2024-03-30},
url = {https://blog.zarathu.com/en/posts/2024-03-30-input-task-button},
langid = {en}
}