0

Sorry for my poor English, I am not a native speaker.

I want to make download button that can download plot resized by jqui_resizable package. enter image description here

I read these URLs for make this. download a plot without replotting in R shiny Shiny.setInputValue only works on the 2nd try

But I have a problem. Like the second URL above, Shiny.setinputvalue only updates the value on the second run.

This is minimum sample code. Can someone please modify this code so that the image can be downloaded on the first click? Or could you please share some information that could help us solve this problem? Thank you in advance.

library(shiny)
library(shinyjqui)
library(magick)
library(xfun)

js <- 'function get_img_src(){
    var src = document.getElementById("myPlot").childNodes[0].src;
    Shiny.setInputValue("img_src", src);
    }'

ui <- fluidPage(
  downloadButton("save_myPlot",onclick="get_img_src();"),
  # plot
  jqui_resizable(plotOutput("myPlot")),
  tags$script(HTML(js))
)

server <- function(input, output, session) {
  
  # downaload handler - save the image
  output$save_myPlot <- downloadHandler(
    filename = function() { 
      paste0("plot_", Sys.Date(), ".png") },
    content = function(file) {
      # get image code from URI
      img_src <- gsub("data:.+base64,", "", input$img_src)
      # decode the image code into the image
      img_src <- image_read(base64_decode(img_src))
      # save the image
      image_write(img_src, file)
    })
  
  # plot
  output$myPlot <- renderPlot(
    plot(rnorm(5), rnorm(5))
  )
}

shinyApp(ui = ui, server = server)

=======================================

(Editted) This problem does not seem to occur in Windows & Chrome environments.
This is my sessionInfo.

R version 4.0.2 (2020-06-22) Platform: x86_64-pc-linux-gnu (64-bit) Running under: Ubuntu 20.04.3 LTS

Matrix products: default BLAS/LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.8.so

locale: 1 LC_CTYPE=ja_JP.UTF-8 LC_NUMERIC=C LC_TIME=ja_JP.UTF-8 LC_COLLATE=ja_JP.UTF-8
[5] LC_MONETARY=ja_JP.UTF-8 LC_MESSAGES=C LC_PAPER=ja_JP.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=ja_JP.UTF-8 LC_IDENTIFICATION=C

attached base packages: 1 stats graphics grDevices utils datasets methods base

other attached packages: 1 xfun_0.31 magick_2.7.3 shinyjqui_0.4.1 wordcloud2_0.2.1 shiny_1.7.2

loaded via a namespace (and not attached): 1 tinytex_0.40 tidyselect_1.1.2 bslib_0.4.0 shinyjs_2.1.0 purrr_0.3.4 lattice_0.20-45
[7] vctrs_0.4.1 generics_0.1.2 htmltools_0.5.3 yaml_2.3.5 utf8_1.2.2 rlang_1.0.3
[13] later_1.3.0 pillar_1.7.0 jquerylib_0.1.4 glue_1.6.2 withr_2.5.0 DBI_1.1.3
[19] lifecycle_1.0.1 fontawesome_0.3.0 htmlwidgets_1.5.4 memoise_2.0.1 fastmap_1.1.0 Cairo_1.6-0
[25] httpuv_1.6.6 parallel_4.0.2 fansi_1.0.3 Rcpp_1.0.8.3 xtable_1.8-4 renv_0.15.5
[31] promises_1.2.0.1 DT_0.23 cachem_1.0.6 RcppParallel_5.1.4 OpenMx_2.20.6 jsonlite_1.8.0
[37] mime_0.12 digest_0.6.29 dplyr_1.0.9 grid_4.0.2 cli_3.3.0 tools_4.0.2
[43] magrittr_2.0.3 sass_0.4.2 tibble_3.1.7 crayon_1.5.1 pkgconfig_2.0.3 MASS_7.3-57
[49] ellipsis_0.3.2 Matrix_1.4-1 shinyBS_0.61.1 lubridate_1.8.0 assertthat_0.2.1 rstudioapi_0.13
[55] R6_2.5.1 compiler_4.0.2

Takuro Ikeda
  • 158
  • 6
  • 2
    I couldn't reproduce the issue, it works fine on my setup (windows / firefox) – HubertL Sep 21 '22 at 18:09
  • 1
    Indeed, it works like this. – Stéphane Laurent Sep 21 '22 at 18:12
  • Thank you for your comment. My development environment is RstudioServer on Ubuntu accessed with Chrome, but after reading your comment, I tried it on Windows and Chrome and it works fine. This problem seems to depend on the environment, so I will check the environment including the package version. Thank you! – Takuro Ikeda Sep 21 '22 at 23:00

1 Answers1

0

I solved this problem by myself. I made two dummy download button.
This method may seem like a lot of hassle, but modularization would eliminate the hassle.

library(shiny)
library(shinyjqui)
library(shinyjs)
library(magick)
library(xfun)

ui <- fluidPage(
  useShinyjs(),
  actionButton("save_myPlot","download", icon = icon("download")),
  actionButton("save_myPlot2","download", icon = icon("download"), style = "visibility: hidden;"),
  downloadButton("save_myPlot_hidden",style = "visibility: hidden;"),
  # plot
  jqui_resizable(plotOutput("myPlot")),
)

server <- function(input, output, session) {
  # I could not get plot_src with Javascript in Linux environment. However, I found that I could get it by running it twice.
  # Therefore, I was able to solve the problem by inserting two dummy buttons: DL button -> DL button 2 -> real DL button.
  observeEvent(input$save_myPlot,{
    shinyjs::runjs("Shiny.setInputValue('plot_src', document.getElementById('myPlot').childNodes[0].src);
                   document.getElementById('save_myPlot2').click();
                   ")
  })
  observeEvent(input$save_myPlot2,{
    shinyjs::runjs("Shiny.setInputValue('plot_src',document.getElementById('myPlot').childNodes[0].src);
                   document.getElementById('save_myPlot_hidden').click();
                   ")
  })
  # downaload handler - save the image
  output$save_myPlot_hidden <- downloadHandler(
    filename = function() { 
      paste0("plot_", Sys.Date(), ".png") },
    content = function(file) {
      # get image code from URI
      plot_src <- gsub("^data.*base64,", "", input$plot_src)
      # decode the image code into the image
      plot_image <- image_read(base64_decode(plot_src))
      # save the image
      image_write(plot_image, file)
    })
  
  # plot
  output$myPlot <- renderPlot(
    plot(rnorm(5), rnorm(5))
  )
}

shinyApp(ui = ui, server = server)
Takuro Ikeda
  • 158
  • 6