0

I have a shiny application that allows my user to explore a dataset. The idea is that the user explores the dataset, and any interesting things the user finds he will share with his client via email. I don't know in advance how many things the user will find interesting. So, next to each table or chart I have an "add this item to the report" button, which isolates the current view and adds it to a reactiveValues list.

Now, what I want to do is the following:

  • Loop through all the items in the reactiveValues list,
    • Generate some explanatory text describing the item (This text should preferably be formatted HTML/markdown, rather than code comments)
    • Display the item
  • Capture the output of this loop as HTML
  • Display this HTML in Shiny as a preview
  • write this HTML to a file

knitr seems to do exactly the reverse of what I want - where knitr allows me to add interactive shiny components in an otherwise static document, I want to generate HTML in shiny (maybe using knitr, I don't know) based on static values the user has created.

I've constructed a minimum not-working example below to try to indicate what I would like to do. It doesn't work, it's just for demonstration purposes.

ui = shinyUI(fluidPage(
  title = "Report generator",
  sidebarLayout(
    sidebarPanel(textInput("numberinput","Add a number", value = 5),
                 actionButton("addthischart", "Add the current chart to the report")),
    mainPanel(plotOutput("numberplot"),
              htmlOutput("report"))
  )
))

server = shinyServer(function(input, output, session){
  #ensure I can plot
  library(ggplot2)

  #make a holder for my stored data
  values = reactiveValues()
  values$Report = list()

  #generate the plot
  myplot = reactive({
    df = data.frame(x = 1:input$numberinput, y = (1:input$numberinput)^2)
    p = ggplot(df, aes(x = x, y = y)) + geom_line()
    return(p)
  })

  #display the plot
  output$numberplot = renderPlot(myplot())

  # when the user clicks a button, add the current plot to the report
  observeEvent(input$addthischart,{
    chart = isolate(myplot)
    isolate(values$Report <- c(values$Report,list(chart)))
  })

  #make the report
  myreport = eventReactive(input$addthischart,{
    reporthtml = character()
    if(length(values$Report)>0){
      for(i in 1:length(values$Report)){
        explanatorytext = tags$h3(paste(" Now please direct your attention to plot number",i,"\n"))
        chart = values$Report[[i]]()
        theplot = HTML(chart) # this does not work - this is the crux of my question - what should i do here?
        reporthtml = c(reporthtml, explanatorytext, theplot)
        # ideally, at this point, the output would be an HTML file that includes some header text, as well as a plot
        # I made this example to show what I hoped would work.  Clearly, it does not work.  I'm asking for advice on an alternative approach.
      }
    }
    return(reporthtml)
  })

  # display the report
  output$report = renderUI({
    myreport()
  })
})

runApp(list(ui = ui, server = server))
CPhil
  • 917
  • 5
  • 11

1 Answers1

0

You could capture the HTML of your page using html2canvas and then save the captured portion of the DOM as a image using this answer, this way your client can embed this in any HTML document without worrying about the origin of the page contents

Community
  • 1
  • 1
RmIu
  • 4,357
  • 1
  • 21
  • 24
  • I'll have to look into this. I would prefer to keep the original formatting rather than saving as an image, so that, for example, the user could copy-paste data tables into Excel, but if I can't get that to work this is a workable substitute. – CPhil Nov 26 '15 at 18:25