Reputation: 95
I am building a Shiny app based on an HTML template and I would like to use plotly for charts. I am struggling with insertion the chart into the template.
The following code works fine:
library(shiny)
library(plotly)
shinyApp(
ui <- fluidPage(plotlyOutput("plot1")),
server <- function(input, output) {
p <- plot_ly(mtcars, x = ~mpg, y = ~wt, type = 'scatter', mode = 'markers')
output$plot1 <- renderPlotly({p})
}
)
But when I change the app to use a template I cannot do it neither by using renderPlotly
nor renderUI
.
<!doctype html>
<html lang="en">
<head>
<script src="shared/jquery.js" type="text/javascript"></script>
<script src="shared/shiny.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="shared/shiny.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="w3.css">
</head>
<body>
<h1>HTML Template UI</h1>
<div id="plot1" class="shiny-plot-output" style="width: 100%; height: 300px; border: 1px solid red"></div>
<div id="plot2" class="shiny-html-output" style="width: 100%; height: 300px; border: 1px solid blue"></div>
</body>
</html>
app.R
library(shiny)
library(plotly)
shinyApp(
ui <- htmlTemplate("template.html"),
server <- function(input, output) {
p <- plot_ly(mtcars, x = ~mpg, y = ~wt)
output$plot1 <- renderPlotly({p})
output$plot2 <- renderUI(HTML(paste(htmltools::tagList(list(p)))))
}
)
Is there any way to use plotly in a Shiny app based on a HTML template?
Upvotes: 4
Views: 1652
Reputation: 9809
There is a more elegant and easy way to achieve this. It is well described in this RStudio article.
To include the necessary HTML & JS-dependencies you include headContent()
in the header of the htmlTemplate. If you need Bootstrap components (actionButtons, tabsetPanel) you also have to include bootstrapLib()
in the header. Make sure those commands are inside double curly brackets like
{{ bootstrapLib() }}
.
You can also place code to generate inputs and outputs (like plotly) in such curly brackets, which will automatically create the html components and include the JavaScript dependencies for you.
This makes the template.html much cleaner.
template.html
<!doctype html>
<html lang="en">
<head>
{{ headContent() }}
</head>
<body>
<h1>HTML Template UI</h1>
<div class="container-fluid">
{{plotlyOutput("plot1") }}
{{uiOutput("plot2") }}
</div>
</body>
</html>
app.R
library(shiny)
library(plotly)
p <- plot_ly(mtcars, x = ~mpg, y = ~wt, type = 'scatter', mode = 'markers')
ui <- htmlTemplate("template.html")
server <- function(input, output) {
output$plot1 <- renderPlotly({p})
output$plot2 <- renderUI(HTML(paste(htmltools::tagList(list(p)))))
}
Upvotes: 1
Reputation: 24252
Try using this template:
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="application/shiny-singletons"></script>
<script type="application/html-dependencies">json2[2014.02.04];jquery[1.12.4];shiny[1.0.5];htmlwidgets[1.0];plotly-binding[4.7.1.9000];bootstrap[3.3.7]</script>
<script src="shared/json2-min.js"></script>
<script src="shared/jquery.min.js"></script>
<link href="shared/shiny.css" rel="stylesheet" />
<script src="shared/shiny.min.js"></script>
<script src="htmlwidgets-1.0/htmlwidgets.js"></script>
<script src="plotly-binding-4.7.1.9000/plotly.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="shared/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<script src="shared/bootstrap/js/bootstrap.min.js"></script>
<script src="shared/bootstrap/shim/html5shiv.min.js"></script>
<script src="shared/bootstrap/shim/respond.min.js"></script>
</head>
<body>
<h1>HTML Template UI</h1>
<div class="container-fluid">
<div id="plot1" class="plotly html-widget html-widget-output" style="width: 100%; height: 300px; border: 1px solid red"></div>
<div id="plot2" class="shiny-html-output" style="width: 100%; height: 300px; border: 1px solid blue"></div>
</div>
</body>
</html>
Upvotes: 0