Home > Net >  How to render a js object with loader in a shiny app
How to render a js object with loader in a shiny app

Time:12-30

This is a follow up question to this

With this app we use a button to take a screenshot. This takes a while, so I would like to implement a loader to the app. For doing this without js code is not a problem for me, but I can't get it to work with js code.

Here is a minimal working example: After clicking the Export to pdf button, there should be a loader shown. I tried shinycssloaders but had no succes:

library(shiny)
library(shinyWidgets)

js <- "
    function Export(){
      var $img = $('#img');
      var width = $img.width();
      var height = $img.height();
      domtoimage.toPng($('html')[0])
        .then(function (blob) {
          var pdf = new jsPDF('p', 'mm', 'a4');
          var imgProps = pdf.getImageProperties(blob);
          var pdfWidth = pdf.internal.pageSize.width;
          var pdfHeight = pdf.internal.pageSize.height;
          var widthRatio = pdfWidth / width;
          var heightRatio = pdfHeight / height;
          var ratio = Math.min(widthRatio, heightRatio);
          var w = imgProps.width * ratio;
          var h = imgProps.height * ratio;
          pdf.addImage(blob, 'PNG', 0, 0, w, h);
          pdf.save('allPage.pdf');
        });
    }
    "

ui <- fluidPage(
  tags$head(
    tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"),
    tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js"),
    tags$script(HTML(js))
  ),
  
  #background image
  tags$img(id = "img",
           src = "http://upload.wikimedia.org/wikipedia/commons/5/5d/AaronEckhart10TIFF.jpg",
           style = 'position: absolute; width: 1250px; height: 880px;'),
  
  div(
    id = "container1",
    style = "position: absolute; left: 30px; top: 170px; display: inline-block; vertical-align: middle; width: 300px;",
    
    actionButton("export", "Export to PDF",
                 onclick = "Export();")
  )
  
)

server <- function(input, output, session) {
  
}

shinyApp(ui, server)

CodePudding user response:

You can set input values via javascript from the client. So you can toggle an input variable, say 'busyWithPDF' between states 0 and 1 by placing these lines in your UI javascript part:

js <- "
    function Export(){
      Shiny.setInputValue('busyWithPDF', 1)
      // code to prepare PDF
      // ...
      // pdf.save('allPage.pdf');
      Shiny.setInputValue('busyWithPDF', 0)
    }
    "

and use this input value, e.g to show/hide a conditional panel (which you could decorate with an infinite input loader)

    shiny::conditionalPanel(condition = 'input.busyWithPDF',
                            div(class = 'well well-info',
                                h1('preparing PDF')
                            )
                            )
  • Related