Display PDF file in R shiny? - r

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) )
}

Related

R Shiny - display image in UI

I am trying to load an image from the www folder (this part works) and then using the image name to display it in the UI. When I try this I get the following error:
Warning: Error in cat: argument 1 (type 'closure') cannot be handled by 'cat'
Here is the fairly simple code
'''
library(shiny)
library(imager)
setwd("E:/CIS590-03I Practical Research Project/Project")
# ui object
ui <- fluidPage(
titlePanel(p("Dog Breed Classification", style = "color:#3474A7")),
sidebarLayout(
sidebarPanel(
fileInput("image",
"Select your image:", placeholder = "No file selected"),
tags$head(
tags$style("body .sidebar {background-color: white; }",
".well {background-color: white ;}"),
),
p("Image to categorize"),
),
mainPanel(htmlOutput("testHTML"),
)
)
)
# server()
server <- shinyServer(function(input, output) {
output$testHTML <- renderText({
paste("<b>Selected image file is: ", input$image$name, "<br>")
reactive(img(
src = input$image$name,
width = "250px", height = "190px"
))
})
})
# shinyApp()
shinyApp(ui = ui, server = server)
'''
Any help will be greatly appreciated.
Thank you,
Bill.
The reason you are getting the error message is because the renderText is returning a reactive function rather than the image HTML tag. reactive shouldn't appear in any render... function.
As #MrFlick has mentioned, renderText will only return a character string to the UI. An alternative for renderUI and uiOutput is renderImage and imageOutput. These will add the uploaded image to the UI in a convenient way, as the render function only requires a list of attributes to give the img tag. This also allows easy inclusion of images that aren't in the www directory.
In the solution below, I have included req to the render functions so that error messages don't appear when no image has been uploaded.
library(shiny)
ui <- fluidPage(
tags$head(
tags$style(
".sidebar {background-color: white;}",
".well {background-color: white;}",
".title-text {color: #3474A7;}"
)
),
h2(
class = "title-text",
"Dog Breed Classification"
),
sidebarLayout(
sidebarPanel(
fileInput(
"image",
"Select your image:",
placeholder = "No file selected"
),
p("Image to categorize")
),
mainPanel(
tags$p(textOutput("filename", container = tags$b)),
imageOutput("testHTML")
)
)
)
server <- function(input, output) {
output$filename <- renderText({
req(input$image)
paste("Selected image file is:", input$image$name)
})
output$testHTML <- renderImage({
req(input$image)
list(
src = input$image$datapath,
width = "250px",
height = "190px"
)
}, deleteFile = TRUE)
}
shinyApp(ui = ui, server = server)

R Fluidrow/Column Font Size

I want to increase the size of the font in a column, under fluid-row. Below is the code I am trying :
fluidRow(
column(12, div(style="height:20px;font-size: 35px;"),'Approval Request Summary'))
Any idea what am I doing wrong?
You have it almost right. You just need to make sure that the text to be rendered is within the call to div() rather than outside it (which is where you currently have it).
The following should give you the results you're expecting:
ui <- fluidPage(
fluidRow(
column(width = 12,
div(style = "height:20px; font-size:35px;",
'Approval Request Summary'))
)
)
shinyApp(ui, server = function(input, output) {})

Specific twitter timeline uiOutput to be reactive in r Shiny

I read all the threads about dynamic ui within the Shiny framework, but I did not find anything that work. I want to display a twitter timeline. This chunk of code works really well :
library(shiny)
library(shinydashboard)
runApp(list(ui = fluidPage(
tags$head(tags$script('!function(d,s,id){var js,fjs=d.getElementsByTagName(s) [0],p=/^http:/.test(d.location)?\'http\':\'https\';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");')),
titlePanel(""),
sidebarLayout(
sidebarPanel()
, mainPanel(
a("Tweets by Andrew Ng",
class="twitter-timeline",
href = "https://twitter.com/AndrewYNg"
)
)
)
)
, server = function(input, output, session){
}
)
)
But when, I try to make it reactive, I only got a link to the twitter timeline:
library(shiny)
library(shinydashboard)
runApp(list(ui = fluidPage(
tags$head(tags$script('!function(d,s,id){var js,fjs=d.getElementsByTagName(s) [0],p=/^http:/.test(d.location)?\'http\':\'https\';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");')),
titlePanel(""),
sidebarLayout(
sidebarPanel()
, mainPanel(
uiOutput("mytimeline")
)
)
)
, server = function(input, output, session){
output$mytimeline <- renderUI({
a("Tweets by Andrew Ng",
class="twitter-timeline",
href = "https://twitter.com/AndrewYNg"
)
})
}
)
)
The Twitter script only loads embedded content when it runs the first time. Since the script is in static UI but the timeline is in dynamic UI, the script will always run before the timeline is inserted.
The Twitter docs have a section about this: https://dev.twitter.com/web/javascript/initialization
You can run twttr.widgets.load() to scan the page for newly added embedded content.
One way to run execute this when inserting embedded content would be to include it in a script tag:
library(shiny)
twitterTimeline <- function(href, ...) {
tagList(
tags$a(class = "twitter-timeline", href = href, ...),
tags$script("twttr.widgets.load()")
)
}
runApp(list(ui = fluidPage(
tags$head(tags$script('!function(d,s,id){var js,fjs=d.getElementsByTagName(s) [0],p=/^http:/.test(d.location)?\'http\':\'https\';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");')),
titlePanel(""),
sidebarLayout(
sidebarPanel()
, mainPanel(
uiOutput("mytimeline")
)
)
)
,
server = function(input, output, session) {
output$mytimeline <- renderUI({
twitterTimeline("https://twitter.com/AndrewYNg", "Tweets by Andrew Ng")
})
}
))
See How to enable syntax highlighting in R Shiny app with htmlOutput for a similar issue with more details

opening webpages within shiny window without opening a separate window

I have an URL which changes with an input on shiny app. I want to open an webpage and display that with in the tab panel of shiny window. Every time I change an input the webpage URL gets updated and I want to show that page in the same tab. As of now the web page opens in a separate window than the shiny window using browseURL function of R.
here is small test example for my case
ui.R
shinyUI(fluidPage(
titlePanel("opening web pages"),
sidebarPanel(
selectInput(inputId='test',label=1,choices=1:5)
),
mainPanel(
htmlOutput("inc")
)
))
server.R
shinyServer(function(input, output) {
getPage<-function() {
return((browseURL('http://www.google.com')))
}
output$inc<-renderUI({
x <- input$test
getPage()
})
})
Dont use browseURL. This explicitly opens the webpage in a new window.
library(shiny)
runApp(list(ui= fluidPage(
titlePanel("opening web pages"),
sidebarPanel(
selectInput(inputId='test',label=1,choices=1:5)
),
mainPanel(
htmlOutput("inc")
)
),
server = function(input, output) {
getPage<-function() {
return((HTML(readLines('http://www.google.com'))))
}
output$inc<-renderUI({
x <- input$test
getPage()
})
})
)
If you want to mirror the page you can use an iframe
library(shiny)
runApp(list(ui= fluidPage(
titlePanel("opening web pages"),
sidebarPanel(
selectInput(inputId='test',label=1,choices=1:5)
),
mainPanel(
htmlOutput("inc")
)
),
server = function(input, output) {
getPage<-function() {
return(tags$iframe(src = "http://www.bbc.co.uk"
, style="width:100%;", frameborder="0"
,id="iframe"
, height = "500px"))
}
output$inc<-renderUI({
x <- input$test
getPage()
})
})
)

displaying a pdf from a local drive in shiny

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.

Resources