displaying a pdf from a local drive in shiny - r

I'm still new to r and shiny, and i'm stumped with what should otherwise be simple logic. I am trying to display pdf files in imageOutput widgets but with no luck. Could someone steer me in the right direction?
sample ui.R
shinyUI(pageWithSidebar(
mainPanel(
selectInput("sel_ed",
label = "View outputs for Ecodistrict:",
choices = c(244,245,247,249),
selected = NULL,
multiple = FALSE),
imageOutput("imp_pdf",width="500px",height="500px")
))
sample server.R
shinyServer(function(input, output, session) {
importance <- function(inputSpecies){
img_dir <- pdf(paste(inputSpecies,"\\models\\MATL\\MATRF_Importance",sep=""))
}
output$imp_pdf <- renderImage({importance(input$sel_ed)})
})
Most of the errors i get have to do with expected character vector arguments, or atomic vectors. I know that shiny is more or less designed to render AND display images or plots but there has to be a way to display pdf's that are already on a local drive..

To embed a PDF viewer (the default PDF viewer of your web browser, pdf.js on mozilla for example) in your Shiny ui, you can use an iframe which the src will be the path to your PDF.
Here is 2 differents ways to include an iframe in your interface :
in the Ui you can directly add an iframe tag with an absolute src attribute as bellow :
tags$iframe(style="height:600px; width:100%", src="http://localhost/ressources/pdf/R-Intro.pdf"))
Or get an URL from the ui in the server , write the iframe tag with the input URL and return the HTML code in a htmlOutput in the ui :
Ui :
textInput("pdfurl", "PDF URL")
htmlOutput('pdfviewer')
Server :
output$pdfviewer <- renderText({
return(paste('<iframe style="height:600px; width:100%" src="', input$pdfurl, '"></iframe>', sep = ""))
})
Note that when pages are loaded with a HTTP(S) protocol (the case of the Shiny app) for security reasons you can't framed locals files with their "file:" URLs. If you want to display locals pdf you should access to them with a http(s): URL, so you have to save them in your www directory (a local web server) and access to files with their http(s): URLs (the URL will be something like http://localhost/.../mypdf.pdf) as in the second iframe of my example. (Then you can't use a fileInput directly, you have to format it)
Ui.R :
library(shiny)
row <- function(...) {
tags$div(class="row", ...)
}
col <- function(width, ...) {
tags$div(class=paste0("span", width), ...)
}
shinyUI(bootstrapPage(
headerPanel("PDF VIEWER"),
mainPanel(
tags$div(
class = "container",
row(
col(3, textInput("pdfurl", "PDF URL"))
),
row(
col(6, htmlOutput('pdfviewer')),
col(6, tags$iframe(style="height:600px; width:100%", src="http://localhost/ressources/pdf/R-Intro.pdf"))
)
)
)
))
Server.R :
shinyServer(function(input, output, session) {
output$pdfviewer <- renderText({
return(paste('<iframe style="height:600px; width:100%" src="', input$pdfurl, '"></iframe>', sep = ""))
})
})
The web pages with the PDF viewers :
Hope this help.

Create a folder called www in the original directory that contains your server.R and ui.R scripts. Place the PDF in the www/ folder, then use something like the code below:
In server.R:
shinyServer(function(input, output) {
observeEvent(input$generate, {
output$pdfview <- renderUI({
tags$iframe(style="height:600px; width:100%", src="foo.pdf")
})
})
})
In ui.R:
shinyUI(fluidPage(
titlePanel("Display a PDF"),
sidebarLayout(
sidebarPanel(
actionButton("generate", "Generate PDF")
),
mainPanel(
uiOutput("pdfview")
)
)
))

Additional to Fabian N.'s answer.
There are two important things:
Make sure you create a R Shiny Web Application from Rstudio. Make sure you run as "Run App". Otherwise, files in "www" folder can not be accessed!
Make sure you create a "www" folder in Web Application directory.

Related

Display PDF file in R shiny?

I want to know if it is possible to create pdf viewer element in R Shiny and change it reactively.
Example:
I have a list of pdf files in folder. Now pdf element should view the selected file and change dynamically with the input.
I have tried this using iframe but it does not change dynamically .Also pdf file should be present in www directory of shiny app....
tags$iframe(src='highl.pdf', height=550)
Can anyone help me to achieve this incase possible ?
I think you probably put the html tags in the ui section, something like this:
ui <- fluidPage(
sidebarLayout(
sidebarPanel( selectinput(inputId = "pdf_selection", .. other stuff ..) ),
mainPanel( tags$iframe(src = input$pdf_selection, height = 550) )
)
)
server <- function(input, output) { .. other stuff .. }
To render the PDF viewer dynamically by the reactive input, you should render it within the server section like:
ui <- fluidPage(
sidebarLayout(
sidebarPanel( selectinput(inputId = "pdf_selection", .. other stuff ..) ),
mainPanel( uiOutput("pdf_viewer") )
)
)
server <- function(input, output) {
output$pdf_viewer <- renderUI( tags$iframe(src = input$pdf_selection, height = 550) )
}

How to use shiny javascript functions with modules?

I want to include some javascript in my shiny module, but regardles of what I tried the javascript is not appear in the final app. What am I doing wrong?
App.r:
library(shiny)
source("examplemod.R")
ui <- fluidPage(
tags$head(
tags$script(src="shinyjavascript.js")
),
sidebarLayout(
sidebarPanel(
examplemodUI("example")
),
mainPanel(
)
)
)
server <- function(input, output) {
callModule(examplemod, "example")
}
shinyApp(ui, server)
Module:
examplemodUI<-function(id){
ns <- NS(id)
tagList(
textOutput(ns("prb"))
)
}
examplemod<- function(input, output, session) {
output$prb<-renderPrint({
input$one
})
}
shinyjavascript.js
$( document ).on("shiny:sessioninitialized", function(event) {
Shiny.onInputChange("one", "noone");
});
First, check that your shinyjavascript.js can be found by the browser. Run your add and open it in a browser. Chrome has a better inspector module than RStudio's built in app viewer (the one that pops up when you run an app). In the browser's Inspector, find the reference to shinyjavascript.js both in the "Elements" pane and that the contents can be loaded in the "Sources" pane.
If it's there, but cannot be loaded, ensure that the file is placed in a subdirectory www from where your app's R source files are located.
If the file is found and loaded, update it to the following for some good ol' fashioned debugging:
console.log('JavaScript file loaded')
$( document ).on("shiny:sessioninitialized", function(event) {
console.log('session initialized')
Shiny.onInputChange("one", "noone");
});
Reload the page and look for these two lines in the console. This will give us a hint to how far your code runs.
Update:
Once satisfied your javascript is loaded and running, we move on to the next. Does your app receive the value and why doesn't it update?
output$prb<-renderPrint is a reactive that only executes if and only if Shiny as prb binded to an output control. This could be your case, or it's that input$one doesn't work. So, we separate the two.
Try to update the following:
server <- function(input, output) {
callModule(examplemod, "example")
observe({cat(input$one, '\n')})
}
This should print 'noone' to the R console.
If that works, move the new observe line to your module:
examplemod<- function(input, output, session) {
output$prb<-renderPrint({
input$one
})
observe({cat(input$one, '\n')})
}
and see if you get a response there.
Update 2 with solution:
So, I've detailed how I would debug these problems. But have found a solution. It requires 3 small changes:
examplemod<- function(input, output, session, one) { # 1
output$prb<-renderPrint({
one() # 2
})
callModule(examplemod, "example", reactive(input$one)) # 3
But I cannot offer any explanation as to why you cannot use input directly...

How to load external image to Shiny

In my current project, I am trying to load images to shiny dashboard using R. The code snippet is as shown below:
dashboardBody(
hr(),
fluidRow(
column(6,align="center",imageOutput("ginger"))
)
)
)
server <- function(input, output) {
output$ginger <- renderImage({
return(list(
src = "images/ginger.jpg",
contentType = "image/jpeg",
width = 300,
height = 200,
alt = "Face"
))
}, deleteFile = FALSE)
Basically, it just display the image on the shiny dashboard. Here the image is stored in the local machine. Now, I want to load image from google drive or from the web. I am trying to load the image from my google drive and URL is https://drive.google.com/file/d/0By6SOdXnt-LFaDhpMlg3b3FiTEU/view.
I could not able to figure out that how to load images from google drive or web in shiny and how to add title in the image also? Am I missing something?
This answer is instructive. Here's a barebones shiny app with an external image call to display the image that you mention on your Google Drive account.
library(shiny)
# Define UI with external image call
ui <- fluidPage(
titlePanel("Look at the image below"),
sidebarLayout(sidebarPanel(),
mainPanel(htmlOutput("picture"))))
# Define server with information needed to hotlink image
server <- function(input, output) {
output$picture <-
renderText({
c(
'<img src="',
"http://drive.google.com/uc?export=view&id=0By6SOdXnt-LFaDhpMlg3b3FiTEU",
'">'
)
})
}
shinyApp(ui = ui, server = server)

In a shiny app how can I force and embedded pdf viewer to refresh when the source file changes

I have used this answer to embed a pdf in my shiny app. When I first generate the pdf through shiny UI inputs and "submit" with an action button the pdf is generated from the UI inputs and displays in the Viewer fine.
However when I change the document through the UI and and submit again the viewer still displays the old report even though the file contents have changed.
How can I force it to display the new pdf?
This is reproducible example of my problem, works best when opened in browser.
ui.R
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
textInput("textin", label = "text input")
, actionButton("makepdf", "Make pdf")
),
mainPanel(
htmlOutput("pdfviewer")
)
)
))
server.R
library(shiny)
shinyServer(function(input, output) {
observeEvent(input$makepdf,{
title <- input$textin
print(title)
pdf("www/test.pdf")
plot(mtcars$mpg,mtcars$disp, main = title)
dev.off()
})
observeEvent(input$makepdf,({
output$pdfviewer <-renderText({
return(paste('<iframe style="height:600px; width:100%" src="'," test.pdf", '"></iframe>', sep = ""))
})
})
)
})
Steps to reporoduce:
Launch app in browser
Type anything in the "text input" box and click "Make pdf"
Type something different in the "text input" box and click "Make pdf"
Observe the pdf viewer still shows output from step 2 even though the source file in your www folder will display the change made in step 3.
I do not know why this works instead of the script in my question but using renderUI in conjunction with tags$iframe as per this answer solves the issue. I welcome any explanations as to why one works and not the other.
Change server.ui to the following:
library(shiny)
shinyServer(function(input, output) {
observeEvent(input$makepdf,{
title <- input$textin
print(title)
pdf("www/test.pdf")
plot(mtcars$mpg,mtcars$disp, main = title)
dev.off()
})
output$pdfviewer<- renderUI({
if((input$makepdf)<1) return()
test <- " test.pdf"
my_test <- tags$iframe(src=test, height=600, width = "100%")#, width=535
print(my_test)
return({my_test})
})
})

R Shiny display output externally hosted image

I have a Shiny app that returns a character string containing the direct URL to an image hosted on the web. I am trying to find a way to display this image directly as an output.
When using renderImage() with src = "image url" the app does not display the image.
Here is an example of the problem:
ui.R
library(shiny)
shinyUI(fluidPage(
headerPanel("render externally hosted Image example"),
mainPanel(
# Use imageOutput to place the image on the page
imageOutput("myImage")
)
))
server.R
library(shiny)
shinyServer(function(input, output, session) {
output$myImage <- renderImage({
list(src = "http://data-informed.com/wp-content/uploads/2013/11/R-language-logo-224x136.png",
contentType = 'image/png',
width = 224,
height = 136,
alt = "This is image alternate text")
})
})
Any help is appreciated!
You could use htmlOutput() in the ui and renderText() in server.
Server.r
src = "https://theWeb/aPictureSomewhere.jpg"
output$picture<-renderText({c('<img src="',src,'">')})
ui.r
htmlOutput("picture")

Resources