How can I print the current page in R shiny web applications? It is possible in HTML by using the command of window.print();. But I could not find and implement its correspondent R Shiny command. What is on my mind is something like the following? How can I call an html command in SERVER?
actionButton("print", "PRINT")
server <- function(input, output) {
observeEvent(input$print, {
window.print();
})
}
This can be done using shinyjs package to call a js function.
library(shiny)
library(shinyjs)
jsCode <- 'shinyjs.winprint = function(){
window.print();
}'
ui <- shinyUI(fluidPage(
useShinyjs(),
extendShinyjs(text = jsCode, functions = c("winprint")),
actionButton("print", "PRINT")
))
server <- shinyServer(function(input, output) {
observeEvent(input$print, {
js$winprint()
})
})
shinyApp(ui, server)
Related
I am having a shiny app with some ui elements.
Is there a way to replace some HTML (e.g. div / div content) with an animation effect, similar to what shinyjs::show(anim=T) does?
library(shiny)
library(shinyjs)
ui <- fluidPage(
shinyjs::useShinyjs(),
actionButton("change","change"),
tags$div(id="someDiv",
"test"),
hidden(tags$div(id="withAnim", "Displayed with animation"))
)
server <- function(input, output) {
observeEvent(input$change, {
shinyjs::html("someDiv", "changed without animation")
shinyjs::delay(1000, show("withAnim", anim=T, animType="fade"))
})
}
shinyApp(ui = ui, server = server)
the shinyjs::html doesn't provide this utility. We can write our own js code and use shinyjs::runjs to run it when button is clicked.
library(shiny)
library(shinyjs)
ui <- fluidPage(
shinyjs::useShinyjs(),
actionButton("change","change"),
tags$div(id="someDiv",
"test"),
hidden(tags$div(id="withAnim", "Displayed with animation"))
)
server <- function(input, output) {
observeEvent(input$change, {
shinyjs::runjs("$('#someDiv').fadeOut(500, function(){$(this).text('changed without animation').fadeIn();})")
shinyjs::delay(1000, show("withAnim", anim=T, animType="fade"))
})
}
shinyApp(ui = ui, server = server)
I recently came across the click() function and want to incorporate this in to my app.
https://www.rdocumentation.org/packages/shinyjs/versions/1.1/topics/click
However attempting to run the given example:
if (interactive()) {
library(shiny)
library(shinyjs)
shinyApp(
ui = fluidPage(
useShinyjs(), # Set up shinyjs
"Count:", textOutput("number", inline = TRUE), br(),
actionButton("btn", "Click me"), br(),
"The button will be pressed automatically every 3 seconds"
),
server = function(input, output) {
output$number <- renderText({
input$btn
})
observe({
click("btn")
invalidateLater(3000)
})
}
)
}
# }
Did not give the desired behaviour. It appears no auto-clicking is taking place! Can anybody explain? Thanks in advance.
I have a code that takes inputs using the readlines(prompt = ) function. Could you tell me which input function in Shiny will be adequate to adapt this code to a Shiny app?
I need an interactive function, I can't use a simple input with selectInput() because I have a lot of readlines(prompt = ) statements.
Something similar to this question:
Include interactive function in shiny to highlight "readlines" and "print"
Florian's answer is nice and easy to use, I would definitely recommend that! But in case you are keen on using prompts for inputs I am adding another solution, using javaScript:
This one shows a prompt when the user presses an actionButton and stores it in an input variable. (it doesn't necessarily have to be after a button press)
library(shiny)
ui <- fluidPage(
tags$head(tags$script("
$(document).on('shiny:inputchanged', function(event) {
if (event.name === 'go') {
var text = prompt('Write me something nice:');
Shiny.onInputChange('mytext', text);
}
});"
)),
actionButton("go", "Click for prompt"),
textOutput("txt")
)
server <- function(input, output, session) {
output$txt <- renderText( {
input$mytext
})
}
shinyApp(ui, server)
Maybe you could use textArea for this purpose. Working example below, hope this helps!
library(shiny)
ui <- fluidPage(
tags$textarea(id="text", rows=4, cols=40),
htmlOutput('val')
)
server <- function(input,output)
{
output$val <- renderText({
text = gsub('\n','<br>',input$text)
text
})
}
shinyApp(ui,server)
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
I'm using modules within my shiny app to display the content of different tabPanels. I would like to be able to travel to the second tab by clicking one button. I have the following code:
library(shiny)
library(shinydashboard)
moduleUI <- function(id){
ns <- NS(id)
sidebarPanel(
actionButton(ns("action1"), label = "Go to tab 2")
)
}
module <- function(input, output, session, openTab){
observeEvent(input$action1, {
openTab("two")
})
return(openTab)
}
ui <- fluidPage(
navlistPanel(id = "tabsPanel",
tabPanel("one", moduleUI("first")),
tabPanel("two", moduleUI("second"))
))
server <- function(input, output, session){
openTab <- reactiveVal()
openTab("one")
openTab <- callModule(module,"first", openTab)
openTab <- callModule(module,"second", openTab)
observeEvent(openTab(), {
updateTabItems(session, "tabsPanel", openTab())
})
}
shinyApp(ui = ui, server = server)
However this only works once. The problem I think, is that the module does not know when a tab is changed in the app. Therefore I'm looking for a way to make sure the module knows which tab is opened so that the actionButton works more that once.
I have considered using input$tabsPanel but I don't know how to implement it.
Help would be greatly appreciated.
The problem is that once the user manually switches back to tab 1, the openTab() does not get updated. So therefore, when you click the actionButton a second time, openTab changes from "two" to "two" (i.e. it stays the same), and therefore your observeEvent is not triggered.
You could add:
observeEvent(input$tabsPanel,{
openTab(input$tabsPanel)
})
So the openTab reactiveVal is updated also when a user manually changes back to tab1 (or any other tab).
You don't need modules to do what you want by the way, but I assume you have a specific reason to use them. For anyone else who wants to achieve the same but does not need modules:
library(shiny)
library(shinydashboard)
ui <- fluidPage(
sidebarPanel(
actionButton(ns("action1"), label = "Go to tab 2")),
navlistPanel(id = "tabsPanel",
tabPanel("one"),
tabPanel("two")
))
server <- function(input, output, session){
observeEvent(input$action1, {
updateTabItems(session, "tabsPanel", "two")
})
}
shinyApp(ui = ui, server = server)