4

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?

2
  • take a look at this: shiny.rstudio.com/articles/html-ui.html Commented Feb 23, 2018 at 14:35
  • @MLavoie Thanks, I have started with that example, but the problem is that they don't use plotly there. Commented Feb 23, 2018 at 14:54

2 Answers 2

1

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)))))
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you SeGa, that sounds like a very good hint, especially that I have now over 2000 lines in my template.
0

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>

enter image description here

4 Comments

Thank you for the answer. I don't have yet these dependencies from your header (html widgets, etc.), so it not working yet on my side, but it looks very promising. I am installing it now :-) Although it would be great to know also a more "native" way of embedding the plotly in the templates, i.e. in some object with class="shiny-x-output".
@mattino Please, could you run your first R code above, click the right button in your browser, choose "visualize source code" (or something similar) and post the result ? Thank you.
The whole html body with plot1 & plot2 divs: imgur.com/a/qksgz
Finally I have generated it on my machine. As hinted by you it was problem with missing links in the HTML template. The solution is to generate first a page with fluidPage() and then copy its header to the template :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.