6.4 Under the hood
A typical web app:
- In the browser (front-end):
- .html file defines the content
- .css files define the style
- javascript handles interactivity
- On the server (back-end):
- Requests received from the client
- R performs computations based on those requests
- Sends responses to the client
6.4.1 HTML - Hypertext markup language
To view the .html for an app
- Open an app in the browser or Rstudio
- “View source” / “Inspect” / Open “Developer Tools”
Typical .html structure:
6.4.2 Writing HTML with shiny
/ htmltools
How to write .html using just R code?
The simplest shiny UI:
The .html body for that UI can be viewed directly:
<div class="container-fluid"></div>
To also include the ‘head’ for the .html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="application/shiny-singletons"></script>
<script type="application/html-dependencies">jquery[3.6.0];shiny-css[1.9.1];shiny-busy-indicators[1.9.1];shiny-javascript[1.9.1];bootstrap[3.4.1]</script>
<script src="jquery-3.6.0/jquery.min.js"></script>
<link href="shiny-css-1.9.1/shiny.min.css" rel="stylesheet" />
<link href="shiny-busy-indicators-1.9.1/busy-indicators.css" rel="stylesheet" />
<script src="shiny-javascript-1.9.1/shiny.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="bootstrap-3.4.1/css/bootstrap.min.css" rel="stylesheet" />
<link href="bootstrap-3.4.1/accessibility/css/bootstrap-accessibility.min.css" rel="stylesheet" />
<script src="bootstrap-3.4.1/js/bootstrap.min.js"></script>
<script src="bootstrap-3.4.1/accessibility/js/bootstrap-accessibility.min.js"></script>
</head>
<body>
<div class="container-fluid"></div>
</body>
</html>
script
and link
elements in the <head>
= dependencies for the site
Adding bare HTML to the shiny-produced HTML
ui_with_raw_html <- shiny::fluidPage(
# some raw html
htmltools::HTML(r"(
<h1>This is a heading</h1>
<ul>
<li>First bullet</li>
<li>Second bullet</li>
</ul>
)"
),
# a shiny text imput
textInput("name", "What's your name?")
)
cat(
as.character(ui_with_raw_html)
)
<div class="container-fluid">
<h1>This is a heading</h1>
<ul>
<li>First bullet</li>
<li>Second bullet</li>
</ul>
<div class="form-group shiny-input-container">
<label class="control-label" id="name-label" for="name">What's your name?</label>
<input id="name" type="text" class="shiny-input-text form-control" value=""/>
</div>
</div>
Using HTML helpers:
ui_from_html_helpers <- shiny::fluidPage(
h1("This is a heading", class = "my-class"),
tags$ul(
tags$li("First bullet"),
tags$li("Second bullet")
),
textInput("name", "What's your name?")
)
cat(
as.character(ui_from_html_helpers)
)
## <div class="container-fluid">
## <h1 class="my-class">This is a heading</h1>
## <ul>
## <li>First bullet</li>
## <li>Second bullet</li>
## </ul>
## <div class="form-group shiny-input-container">
## <label class="control-label" id="name-label" for="name">What's your name?</label>
## <input id="name" type="text" class="shiny-input-text form-control" value=""/>
## </div>
## </div>
6.4.3 CSS - Cascading Style Sheets
CSS
- isn’t covered in the chapter (but links provided)
- but underlies how bootstrap styles your shiny app
Much more detail at
How does the browser display a site / app?
6.4.4 Using CSS to style a shiny app
A simple CSS file to set any text with “my-class” as class to red
- Put static files (javascript / css) in the
./www
subdirectory of your app - Include your files using
tags$link
when defining the UI - Note: the path in the link should be “style.css” not “www/style.css”
# ./examples/06-layout_themes_html-css_example/app.R
library(shiny)
ui <- shiny::fluidPage(
tags$link(rel = "stylesheet", type = "text/css", href = "style.css"),
h1("This is a heading", class = "my-class"),
textInput("name", "What's your name?")
)
server <- function(input, output, session) {}
shinyApp(ui, server)
You can write custom rules to style based on
- html element (
p
,h1
, …), - attributes
- IDs
- and on interactive things (eg, when the mouse hovers)