I want to customize my PDF output by :
Centering my data table
Enlarging logo
Writing Data Extraction below the logo
Making the table pretty
I think that we need to work with JavaScript to solve this kind of problem, if anyone knows how to do so, please tell me
Thank you so much for your collaboration!
library(shiny)
library(DT)
library(base64enc)
ui <- fluidPage(
tags$head(
tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"),
tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js")
),
br(),
DTOutput("dtable")
)
server <- function(input, output, session){
output[["dtable"]] <- renderDT({
datatable(
iris[1:5,],
extensions = "Buttons",
options = list(
dom = "Bfrtip",
buttons = list(
list(
extend = "pdfHtml5",
customize = JS(
"function(doc) {",
" doc.content.splice( 1, 0, {",
" margin: [ 0, 0, 0, 12 ],",
" alignment: 'center',",
sprintf(
" image: '%s',",
dataURI(
file = "https://www.r-project.org/logo/Rlogo.png",
mime = "image/png"
)
),
" width: 50",
" })",
"}"
)
)
)
)
)
})
}
shinyApp(ui, server)
Related
I try to collapse a box with an action. This code works in shinydashboard how should I change jscode for doing same thing in bs4Dash ? Any idea?
library(shiny)
library(shinydashboard)
library(shinyjs)
jscode <- "
shinyjs.collapse = function(boxid) {
$('#' + boxid).closest('.box').find('[data-widget=collapse]').click();
}
"
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
useShinyjs(),
extendShinyjs(text = jscode, functions = c("collapse")),
actionButton("bt2", "Collapse box2"),
br(), br(),
box(id = "box2", collapsible = TRUE, p("Box 2"))
)
)
server <- function(input, output) {
observeEvent(input$bt2, {
js$collapse("box2")
})
}
shinyApp(ui, server)
bs4Dash lets you do this without any javascript.
observeEvent(input$bt2, {
updateBox('box2', action = 'toggle')
})
App:
library(shiny)
library(bs4Dash)
library(shinyjs)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
actionButton("bt2", "Collapse box2"),
br(),
br(),
box(
id = "box2",
collapsible = TRUE,
p("Box 2")
)
)
)
server <- function(input, output) {
observeEvent(input$bt2, {
updateBox("box2", action = "toggle")
})
}
shinyApp(ui, server)
Using shiny 1.6.0 and bslib 0.3.0.
This work as expected:
library(shiny)
ui <- navbarPage(
title = "Minimal Example Issue",
id = "tabs",
header = conditionalPanel(
condition = "input.tabs == 'tab_1'",
HTML("Special tab 1")
),
tabPanel("tab_1", "Hello"),
tabPanel("tab_2", "Hi")
)
server <- function(input, output) {}
shinyApp(ui = ui, server = server)
This doesn't as the condition isn't met on selection of tab_1:
library(shiny)
library(bslib)
ui <- page_navbar(
title = "Minimal Example Issue",
id = "tabs",
header = conditionalPanel(
condition = "input.tabs == 'tab_1'",
HTML("Special tab 1")
),
nav("tab_1", "Hello"),
nav("tab_2", "Hi")
)
server <- function(input, output) {}
shinyApp(ui = ui, server = server)
I would like to understand which JS element has replaced the input.tabs in the second example.
upgrading shiny to 1.7.0 (now on CRAN) fix it
Seems like shiny cannot recognize my .js file. Question is why?
Inlined js script text runs smoothly:
library(shiny)
header = dashboardHeader(disable = TRUE)
sidebar = dashboardSidebar(disable = TRUE)
body = dashboardBody(
shiny::tags$script(
HTML("document.body.style.backgroundColor = 'skyblue';")),
)
ui = dashboardPage(header = header, sidebar = sidebar, body = body)
server = function(input, output, session){
}
shinyApp(ui, server)
However when i embedd my .js file (myscript.js stored within www subdirectory)
document.body.style.backgroundColor = "skyblue";
$("firstinput").on("keypress", function(){
alert("Pressed");
})
$(document).on('shiny:connected', function(event) {
alert('Connected to the server');
})
...like this:
library(shiny)
header = dashboardHeader(disable = TRUE)
sidebar = dashboardSidebar(disable = TRUE)
body = dashboardBody(
shiny::tags$head(
shiny::tags$script(
src = "myscript.js"
)),
HTML('<input type="button" id="firstinput">')
)
ui = dashboardPage(header = header, sidebar = sidebar, body = body)
server = function(input, output, session){
}
shinyApp(ui, server)
nothing is applied... How comes?
No need of tags$head(). The following works fine.
tags$script(src = "myscript.js")
I have a shiny app that I would like to end the session every time, I close the browser. I researched around and most developers proposed adding this snippet on my server.
session$onSessionEnded(function() {
stopApp()
})
A minimal example is provided below;
rm(list=ls())
library(shiny)
doshiny <- function() {
app=shinyApp(
ui = fluidPage(
textInput("textfield", "Insert some text", value = "SomeText")
),
server = function(input, output, session) {
session$onSessionEnded(function() {
stopApp()
})
}
)
runApp(app)
}
openshiny <- function() {
doshiny()
print("Finished.")
}
openshiny()
the problem with this example I keep asking myself where should I place my other the other lines in the server? for instance, if I want to plot a histogram which way do I write my server?
is it
server = function(input, output, session) {
session$onSessionEnded(function() {
hist(data)
stopApp()
})
}
)
or
server = function(input, output, session) {
hist(data)
session$onSessionEnded(function() {
stopApp()
})
}
)
I am just seeking a more working example
If you want to plot your histogram while the session is active, take the second option. As mentioned by #Waldi the first option plots your histogram when the session is ended, and the user will thus never see the histogram. See here an example of the two options:
First option: we never see the table
rm(list=ls())
library(shiny)
doshiny <- function() {
app=shinyApp(
ui = fluidPage(
textInput("textfield", "Insert some text", value = "SomeText"),
dataTableOutput('table')
),
server = function(input, output, session) {
session$onSessionEnded(function() {
output$table <- renderDataTable(iris)
stopApp()
})
}
)
runApp(app)
}
openshiny <- function() {
doshiny()
print("Finished.")
}
openshiny()
Second option: we see the table
rm(list=ls())
library(shiny)
doshiny <- function() {
app=shinyApp(
ui = fluidPage(
textInput("textfield", "Insert some text", value = "SomeText"),
dataTableOutput('table')
),
server = function(input, output, session) {
output$table <- renderDataTable(iris)
session$onSessionEnded(function() {
stopApp()
})
}
)
runApp(app)
}
openshiny <- function() {
doshiny()
print("Finished.")
}
openshiny()
I'm building a Shiny app that lets users upload images to the server. I'd like to display the image on the screen without having to upload it first and then get the rendered output back. Is this possible?
This is my code right now. You can select an image file, which gets uploaded. The image is then rendered from the file on the server side, after it's been received. I'd like to avoid the roundtrip.
UI
fluidPage(
titlePanel("File upload"),
sidebarLayout(
sidebarPanel(
fileInput("img", "Choose image file",
accept=c("image/jpeg", "image/x-windows-bmp"))
),
mainPanel(
imageOutput("picture", width="500px", height="500px")
)
)
)
Server
function(input, output, session)
{
output$picture <- renderImage({
imgFile <- input$img
if(is.null(imgFile))
return(list(src=""))
list(src=imgFile$datapath, alt=imgFile$name, contentType=imgFile$type)
}, deleteFile=FALSE)
# do more stuff with the file
}
You can use package shinyjs to call FileReader from HTML 5 read here
library(shinyjs)
shinyApp(ui = fluidPage(
useShinyjs(),
titlePanel("File upload"),
sidebarLayout(
sidebarPanel(
fileInput("img", "Choose image file",
accept=c("image/jpeg", "image/x-windows-bmp")),
HTML('<output id="list"></output>')
),
mainPanel(
imageOutput("picture", width="500px", height="500px")
)
)),
server = function(input, output, session){
shinyjs::runjs("
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class=\"thumb\" src=\"', e.target.result,
'\" title=\"', escape(theFile.name), '\"/>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
document.getElementById('img').addEventListener('change', handleFileSelect, false);")
output$picture <- renderImage({
imgFile <- input$img
if(is.null(imgFile))
return(list(src=""))
list(src=imgFile$datapath, alt=imgFile$name, contentType=imgFile$type)
}, deleteFile=FALSE)
})
Edit:
Okay, I now the question is clear for me, I hope :).
The problem is that pictures are added within <output id="list"></output>. So I would suggest clearing it before a new picture is added with: document.getElementById('list').innerHTML = ''
library(shiny)
library(shinyjs)
shinyApp(ui = fluidPage(
useShinyjs(),
titlePanel("File upload"),
sidebarLayout(
sidebarPanel(
fileInput("img", "Choose image file",
accept=c("image/jpeg", "image/x-windows-bmp"))
),
mainPanel(
HTML('<output id="list"></output>')
)
)),
server = function(input, output, session){
shinyjs::runjs("
function handleFileSelect(evt) {
document.getElementById('list').innerHTML = ''
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class=\"thumb\" src=\"', e.target.result,
'\" title=\"', escape(theFile.name), '\"/>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
document.getElementById('img').addEventListener('change', handleFileSelect, false);")
})