Add a second image in the navbar of a Shiny application - r

I have the following snippet of code:
shinyUI(fluidPage(
useShinyjs(),
shinyjs::hidden(div(
id = "application",
navbarPage(
title = div(img(src="img_1.png", filetype="image/png"), "Indicators"),
id = "tabs",
tabpanel("Admin", ...)
tabpanel("User", ...)
)
))
))
I would like to add a second image, let's call it img_2.png to the right of the navbar, i.e. at the end of the navbar itself. Maybe the fact that I used title = forces me to place only one image in the navbar. Could anyone help me?

you can add an additional img tag and an style parameter, that sets the position to the right side:
title = div(img(src="img_1.png", filetype="image/png"), "Indicators", img(src="img_1.png", filetype="image/png", style = "position: fixed;right: 20px;"))

Related

Aligning Multiple Action Buttons in Shiny Dashboard Header

This SO post describes how to add an actionButton to the top right of the dashboardHeader in a shinydashboard. I would like to add two action buttons next to each other in the dashboardHeader. How can I place the buttons within the header bar so that they do not overlap? More specifically, is there a way to move a button to the left and centre it vertically within the dashboardHeader?
Perhaps you are looking for this
ui <- dashboardPage(
dashboardHeader(title = div("Testing Work Space",
img(src = 'YBS.png',
title = "Just a Test Application", height = "30px"),
style = "position: relative; margin:-3px 0px 0px 5px; display:right-align;"
),
titleWidth=350,
tags$li(div(
img(src = 'YBS.png',
title = "A Test Graphics Application", height = "30px"),
style = "padding-top:15px; padding-right:100px;"),
class = "dropdown"),
tags$li(a(href = 'http://www.cnn.com',
icon("power-off"),
title = "CNN Home"),
class = "dropdown"),
tags$li(a(href = 'https://en.wikipedia.org/wiki/Mouse',
tags$img(src = 'mouse.png', height = "30px"),
title = "Mouse Home"),
class = "dropdown")
),
dashboardSidebar(),
dashboardBody()
)
server <- function(input, output,session) {}
shinyApp(ui, server)
You can adjust padding and margin to suit your needs. Also, you can add multiple actionButtons.
I can't answer your question directly because I have only used Flexdashboard. But there is a shinyWidgets package that contains a DropDown widget that allows you to embed multiple widgets into the DropDown. So if the dashboard header only allows a single widget, you could use a dropdown widget to access multiple widgets indirectly See:
http://shinyapps.dreamrs.fr/shinyWidgets/
And the dropdowns & sweetalert menu item. The sample dropdowns there contain links to the underlying shinyWidgets code.

Ghost tab at the end of navbar page within shiny context

As shown in the below image, I have a problem with a ghost tab that appears at the end of my navbar page.
The ghost tab disappears when the code below at the end of ui is deleted. The code is related to the loading sign. How can I fix this?
hidden(
div(
id = "app-content"
#p("")
)
)
I fixed this by moving the mentioned code to right after ui <- fluidPage(.
ui <- fluidPage(
hidden(
div(
id = "app-content"
#p("")
)
),

Adding images in the title and at the right of navbarPage

I would like to include a small image at the left of the title of my navbarPage, and to include another image completely at the right of this same navbarPage. I found this answer which provides the same layout than the one I would like to have. The problem is that this solution does not provide a fully reproducible example and I can't figure out how to include the chunks of code in the ui part.
Does anybody know how to make a reproducible example from this answer?
Here's what I've tried so far:
library(shiny)
ui <- navbarPage(
tags$script(HTML("var header = $('.navbar > .container-fluid');
header.append('<div style=\"float:right\"><h3>This is R</h3></div>');"
)),
tags$script(HTML("var header = $('.navbar > .container-fluid');
header.append('<div style=\"float:right\"><img src=\"image.png\" alt=\"alt\" style=\"float:right;width:33px;height:41px;padding-top:10px;\"> `</div>');
console.log(header)")
),
title = div(img(src="image.png", height = '40px', width = '40px'), "something"),
tabPanel("foo")
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
This is the image called image.png. I put it in the www folder, which is placed in my app directory.
There are mainly two things to solve:
* some text is displayed on the below the navbar whereas it shouldn't be displayed at all
* the image and the text at the left are not centered
I did not make any change to your code (well except the tags$head() at the begining, but that's an add on).
The only problem with your code is not the problem in your code, is the problem in your files structure.You have to place your images inside a new folder called www (Note that the folder www is in the same place as your R code which is app.R or ui.R).
library(shiny)
ui <- fluidPage(
tags$head(
tags$link(rel = "shortcut icon", type = "image/png", href = "image.png"),
tags$title("Browser tab title")
),
navbarPage(
tags$script(HTML("var header = $('.navbar > .container-fluid');
header.append('<div style=\"float:right\"><h3>This is R</h3></div>');"
)),
tags$script(HTML("var header = $('.navbar > .container-fluid');
header.append('<div style=\"float:right\"><img src=\"image.png\" alt=\"alt\" style=\"float:right;width:33px;height:41px;padding-top:10px;\"> </div>');
console.log(header)")
),
title = tags$div(img(src="image.png", height = '40px', width = '40px'), "something"),
tabPanel("foo")
)
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
Note: I've added the navbarPage inside a fluidPage because without the fluidPage, the title of the NavBarPage will be the title in the browser tab!But now the main UI is the fluidPage so it's title will be the browser title. this also gives you flexiblity to add a new image for the browser tab, different from the navbar page's tab.
Here's the screen shot of the output.
Hope this helps!

Direct link to tabItem with R shiny dashboard

I am using the shiny dashboard template to generate my web UI.
I'd like to dynamically generate an infobox when a computation is completed with a link directed to one of the tabItems in dashboardBody.
For example,
I can put this in my tabItem1 output,
renderInfoBox({
infoBox("Completed",
a("Computation Completed", href="#tabItem2"),
icon = icon("thumbs-o-up"), color = "green"
)
})
But the problem is that when I click the link, it does nothing. I would like it jumps to tabItem2. The link href seems valid when I hover on it.
Thanks!
Update:
Other than using Javascripts, looks like using actionLink and updateTabItems functions in shinydashboard package will work as well.
I apologize for the lengthy code sample, but I had to copy an example with tabItems from the shinydashboard homepage.
Your approach has only few problems. First, if you would inspect the menuItems, you'd see that the actual tab's id is not tabItem2, but shiny-tab-tabItem2. This, plus the extra attribute data-toggle="tab" within the a tag would suffice to open the desired tab. Snippet:
a("Computation Completed", href="#shiny-tab-tabItem2", "data-toggle" = "tab")
But, this has its limits. First and most obvious, the state of the menuItem in the sidebar is not set to active. This looks very odd and one might not be convinced, that one has been moved to another tab.
Second, and less obvious, if you listen to tab changes (on the server side), you will not get information about this tab switch. Those are triggered by the menuItem being clicked, and the tab itself will not report if it is visible or hidden.
So, my approach will be to simulate that the corresponding menuItem is clicked, and thus, all the above problems are solved.
Code example:
library(shiny)
library(shinydashboard)
ui <- shinyUI(
dashboardPage(
dashboardHeader(title = "Some Header"),
dashboardSidebar(
sidebarMenu(
menuItem("Computations", tabName = "tabItem1", icon = icon("dashboard")),
menuItem("Results", tabName = "tabItem2", icon = icon("th"))
)
),
dashboardBody(
tags$script(HTML("
var openTab = function(tabName){
$('a', $('.sidebar')).each(function() {
if(this.getAttribute('data-value') == tabName) {
this.click()
};
});
}
")),
tabItems(
tabItem(tabName = "tabItem1",
fluidRow(
box(plotOutput("plot1", height = 250)),
box(
title = "Controls",
sliderInput("slider", "Number of observations:", 1, 100, 50)
)
),
infoBoxOutput("out1")
),
tabItem(tabName = "tabItem2",
h2("Widgets tab content")
)
)
)
)
)
server <- function(input, output){
histdata <- rnorm(500)
output$plot1 <- renderPlot({
data <- histdata[seq_len(input$slider)]
hist(data)
})
output$out1 <- renderInfoBox({
infoBox("Completed",
a("Computation Completed", onclick = "openTab('tabItem2')", href="#"),
icon = icon("thumbs-o-up"), color = "green"
)
})
}
shinyApp(ui, server)
Note, that the only important thing is the onclick property, not an href. This means, that every div or other element can be used to create this link. You could even have just the thumbs-up image with this onclick command.
If you have more questions, please comment.
Best Regards
Edit: Whole infoBox clickable.
This is an answer to a comment by OmaymaS. The point was to make the infoBox a clickable container. To achieve this, one can define a new function that makes a somewhat different infoBox. The custom box will be as follows:
customInfoBox <- function (title, tab = NULL, value = NULL, subtitle = NULL, icon = shiny::icon("bar-chart"), color = "aqua", width = 4, href = NULL, fill = FALSE) {
validateColor(color)
tagAssert(icon, type = "i")
colorClass <- paste0("bg-", color)
boxContent <- div(class = "info-box", class = if (fill) colorClass,
onclick = if(!is.null(tab)) paste0("$('.sidebar a')).filter(function() { return ($(this).attr('data-value') == ", tab, ")}).click()"),
span(class = "info-box-icon", class = if (!fill) colorClass, icon),
div(class = "info-box-content",
span(class = "info-box-text", title),
if (!is.null(value)) span(class = "info-box-number", value),
if (!is.null(subtitle)) p(subtitle)
)
)
if (!is.null(href)) boxContent <- a(href = href, boxContent)
div(class = if (!is.null(width)) paste0("col-sm-", width), boxContent)
}
This code is copied from the original infoBox function definition and only the line with onclick is new. I also added the openTab function (with some twitches) right inside the container such that you dont need to worry where to put this function inside the view. Might be a bit overloaded i feel.
This custom info box can be used exactly like the default one and if you pass the additional tab argument, the link to the sidebar is added.
Edit: Subtitle exploit
As Alex Dometrius mentioned, the use of subtitle crashes this functionality. This is because the script tag that was inserted, on accident, was used as the subtitle argument in order to be rendered with the box. To free up this spot, I edited the main example up top such that the script tag is sitting top level in the dashboardBody (literally anywhere in the ui would be fine).
(To avoid confusion: in Version 1, the tags$script was supplied inside of infobox where it was interpreted as the subtitle parameter.)

Adding a company Logo to ShinyDashboard header

So just curious, is there any way to add a company logo to the header of a ShinyDashboard? As I am looking at the documentation, it describes changing the "logo" in the CSS, this is just configuring what goes in the upper left hand corner though as far as I can tell and I would like to keep my title there.
I am not using the drop down menus and so I would like to add my company logo on the top right where the red box is.
Does anyone have any idea how this can be done with Shinydashboard? Thanks.
Update 2020-10-27
For users that are comfortable with HTML or want more flexibility around their user interface and have access to a front end developer, I recently discovered you can use HTML to build the entire user interface. There is a Shiny article about it here. This would allow the entire branding and layout to be done in a way that could comply with your company standards if desired. Hope this helps.
I've been working with a bit of a hack for this, (and I know you didn't ask for it, but here's a clickable logo while we're at it):
library(shiny)
library(shinydashboard)
dbHeader <- dashboardHeader()
dbHeader$children[[2]]$children <- tags$a(href='http://mycompanyishere.com',
tags$img(src='logo.png',height='60',width='200'))
dashboardPage(
dbHeader,
dashboardSidebar(),
dashboardBody()
)
So this nests a shiny.tag inside the header. The second slot in this particular shiny object is the logo slot (You'll need a 'logo.png' in your /www/ folder in the app directory)
EDIT:
I just checked, and as of right now, this hack should no longer be necessary, you can insert the html directly from the dashboardHeader function via the title= parameter, (Before, that parameter was enforcing text only),
I think the answer might still be useful as a method to modify existing shiny functions where things ARE hardcoded in though.
Here's the method now:
dashboardPage(
dashboardHeader(title = tags$a(href='http://mycompanyishere.com',
tags$img(src='logo.png')))
or, adding a little more magic to the logo (I also use my logo as a loading bar):
# Takes a location 'href', an image location 'src', a loading gif 'loadingsrc'
# height, width and alt text, and produces a loading logo that activates while
# Shiny is busy
loadingLogo <- function(href, src, loadingsrc, height = NULL, width = NULL, alt = NULL) {
tagList(
tags$head(
tags$script(
"setInterval(function(){
if ($('html').attr('class')=='shiny-busy') {
$('div.busy').show();
$('div.notbusy').hide();
} else {
$('div.busy').hide();
$('div.notbusy').show();
}
},100)")
),
tags$a(href=href,
div(class = "busy",
img(src=loadingsrc,height = height, width = width, alt = alt)),
div(class = 'notbusy',
img(src = src, height = height, width = width, alt = alt))
)
)
}
dashboardBody(
dashboardHeader(title = loadingLogo('http://mycompanyishere.com',
'logo.png',
'loader.gif'),
dashboardSidebar(),
dashboardBody()
)
Here's my hack (put your logo, as has been mentioned before, into a www subdirectory of your app directory).
Because dashboardHeader() expects a tag element of type li and class dropdown, we can pass such elements instead of dropdownMenus:
library(shiny)
library(shinydashboard)
dbHeader <- dashboardHeader(title = "My Dashboard",
tags$li(a(href = 'http://shinyapps.company.com',
icon("power-off"),
title = "Back to Apps Home"),
class = "dropdown"),
tags$li(a(href = 'http://www.company.com',
img(src = 'company_logo.png',
title = "Company Home", height = "30px"),
style = "padding-top:10px; padding-bottom:10px;"),
class = "dropdown"))
server <- function(input, output) {}
shinyApp(
ui = dashboardPage(
dbHeader,
dashboardSidebar(),
dashboardBody()
),
server = server
)

Resources