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
Related
I am trying to use a button to change pages in a shiny app. I have found examples like this one that seem pretty straight forward but for some reason I am not able to make it work. Below is a reproducible example I created in an app.R file. This creates a two page app with a button on the first page but clicking the button does not move you to the second page. Any tips would be greatly appreciated.
pageButtonUi <- function(id) {
actionButton(NS(id, "page_change"),
label="Change the Page")
}
pageButtonServer <- function(id) {
moduleServer(id, function(input, output, session) {
observeEvent(input$page_change, {
updateNavbarPage(session=session,
inputId="pages",
selected="second_page")
})
})
}
ui <- navbarPage(
title="test",
id="pages",
tabPanel(title="first page",
sidebarLayout(
sidebarPanel(
pageButtonUi("page")
),
mainPanel(
)
)
),
tabPanel(title="second_page", "second_page")
)
server <- function(input, output, session) {
pageButtonServer("page")
}
shinyApp(ui, server)
You are using shiny modules. The tabPanel is defined in the top-level UI, but your are trying to use a lower-level (module) server to update the top-level UI. This will not work. So you need to use top-level server to update top-level UI. In other words, you need to pass the parent session object to your module.
This is how to fix:
library(shiny)
pageButtonUi <- function(id) {
actionButton(NS(id, "page_change"),
label="Change the Page")
}
pageButtonServer <- function(id, parentSession) {
moduleServer(id, function(input, output, session) {
observeEvent(input$page_change, {
updateNavbarPage(session=parentSession,
inputId="pages",
selected="second_page")
})
})
}
ui <- navbarPage(
title="test",
id="pages",
tabPanel(title="first page",
sidebarLayout(
sidebarPanel(
pageButtonUi("page")
),
mainPanel(
)
)
),
tabPanel(title="second_page", "second_page")
)
server <- function(input, output, session) {
pageButtonServer("page", parentSession = session)
}
shinyApp(ui, server)
This is not easy to understand even for advanced users. Try to read Rstudio articles see how they define session will be helpful.
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) )
}
I would like to add a tooltip for navbarMenu in Shiny app. Similar question asked here but, there is no answer.Here is my reproducible code
library(shiny)
library(shinyBS)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(),
mainPanel(tabsetPanel(
navbarMenu("Tab1",bsTooltip(id="Tab1", title="Short description for the tab", trigger = "hover"),
tabPanel("Tab1.1"),
tabPanel("Tab1.2")),
tabPanel("Tab2",tabsetPanel(
tabPanel("Tab2.1"),
tabPanel("Tab2.2"))),
tabPanel("Tab3",tabsetPanel(
tabPanel("Tab3.1"),
tabPanel("Tab3.2"),
tabPanel("Tab3.3")))
)))))
server <- function(input, output) {}
shinyApp(ui = ui, server = server)
During my research I found this solution R Shiny: Use navbarPage with bsModal by shinyBS, but for bsModel.
Also, there is a procedure mentioned here which is based in java-script.I know both solutions are for tabpanel but I believe it's the same problem, which is navbarMenu and tabpanel don't have an id.
I'm statistician and I don't have background in HTML or java-script to rewrite the attribute for the tab title or navbarMenu.
I hope I phrase my question in a clear manner. Thanks in advance for your time and kind help.
you can use HTML wenn passing the Title of the Tabs. in this case I just pt the title in a span and added the attribute titlewhich is the attribute HTML uses default for mouse-overs. For me this is much sinpler the trying to add it over shinyBS.
library(shiny)
library(shinyBS)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(),
mainPanel(tabsetPanel(
navbarMenu(span("Tab1",title="Short description for the tab" ),
tabPanel("Tab1.1"),
tabPanel("Tab1.2")),
tabPanel("Tab2",tabsetPanel(
tabPanel("Tab2.1"),
tabPanel("Tab2.2"))),
tabPanel("Tab3",tabsetPanel(
tabPanel("Tab3.1"),
tabPanel("Tab3.2"),
tabPanel("Tab3.3")))
)))))
server <- function(input, output) {}
shinyApp(ui = ui, server = server)
hope this helps!
I found another solution using javascript. Perhaps it may be more useful.
library(shiny)
shinyApp(
ui = navbarPage(
tags$script(HTML('
$( document ).on("shiny:sessioninitialized", function(event) {
$(\'span[data-toggle="tooltip"]\').tooltip({
html: true
});
});'
)),
navbarMenu(
"Menu"
,tabPanel(span("navbarTitle 1",title="XXX",`data-toggle`="tooltip"),
tabsetPanel(
tabPanel(span("Tab 1", title = "aaa",`data-toggle`="tooltip")),
tabPanel(span("Tab 2",title="bbb",`data-toggle`="tooltip")),
tabPanel(span("Tab 3",title="ccc",`data-toggle`="tooltip"))
)
)
,tabPanel( "navbarTitle 2")
)
),
server = function(input, output) {
}
)
My objective is to create a ShinyApp that opens a new empty UI whenever user clicks on submitButton.
Currently this is my code below. If the user types something in the text box and press Submit. The app shows what the user typed in the main panel. However I dont want to see the text, instead when the user clicks on the submit button , it should open a new empty UI.
ui = shinyUI(fluidPage(
titlePanel("submitButton example"),
fluidRow(
column(3, wellPanel(
textInput("text", "Text:", "text here"),
submitButton("Submit")
)),
verbatimTextOutput("text")
)
)
)
server = function(input, output) {
output$plot1 <- renderPlot({
hist(rnorm(input$n))
})
output$text <- renderText({
paste("Input text is:", input$text)
})
}
shinyApp(ui=ui, server=server)
Is this possible ? Any tips or pointers are appreciated.
Well, this is not yet very functional, but does what you asked for.
ui = shinyUI(fluidPage(
titlePanel("submitButton example"),
fluidRow(
uiOutput("newWindowContent", style = "display: none;"),
tags$script(HTML("
$(document).ready(function() {
if(window.location.hash != '') {
$('div:not(#newWindowContent)').hide();
$('#newWindowContent').show();
$('#newWindowContent').appendTo('body');
}
})
")),
a(href = "#NEW", target = "_blank",
actionButton("Submit", "Submit")
)
))
)
server = function(input, output) {
output$newWindowContent <- renderUI({
"Welcome to your new window!"
})
}
shinyApp(ui=ui, server=server)
The app is created, such that the ui created in newWindowContent is displayed in the new window. Sadly, new windows are somewhat cut off from the parent page, such that there is no easy way to configure each page independently. At the moment, all show the same content. None have reactivity features. I guess there can be initial configurations, if one uses the window's hash. But this works only client sided.
Nevertheless, it's a good start!
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()
})
})
)