I would like to know what was the easiest way to set up a different image to each of my 3 shiny main tabpanels ?
I thought that using setBackgroundImage(src = "image1.jpg", shinydashboard = TRUE), setBackgroundImage(src = "image2.jpg", shinydashboard = TRUE), etc. in each of them would do the trick but unfortunately it is not that simple.
I guess I shall use some CSS but I'm very new to this and I didn't find a solution to my problem yet.
Any guess about how I should do that ?
Minimal app:
library(shiny)
library(shinyWidgets)
ui <- shinyUI(navbarPage(id="Test", "TEST",
header = tagList(
useShinydashboard()
),
tabPanel(
"Welcome", value="welcome",
verbatimTextOutput("text1")),
tabPanel(
"Tab1", value="first_tab",
verbatimTextOutput("text2")),
tabPanel(
"Tab2", value="second_tab",
verbatimTextOutput("text3"))))
server <- shinyServer(function(input, output, session){
output$text1 <- renderText("Trying to set up a first background image in this whole panel")
output$text2 <- renderText("Trying to set up a second background image in this whole panel")
output$text3 <- renderText("Trying to set up a third background image in this whole panel")
})
shinyApp(ui, server)
You can use the CSS background-image Property to achive this:
library(shiny)
library(shinyWidgets)
# remove /* ... */ to use the arguments
backgroundImageCSS <- "/* background-color: #cccccc; */
height: 91vh;
background-position: center;
background-repeat: no-repeat;
/* background-size: cover; */
background-image: url('%s');
"
ui <- shinyUI(navbarPage(id="Test", "TEST",
header = tagList(
useShinydashboard()
),
tabPanel(
"Welcome", value="welcome",
verbatimTextOutput("text1"),
style = sprintf(backgroundImageCSS, "https://images.plot.ly/language-icons/api-home/r-logo.png")
),
tabPanel(
"Tab1", value="first_tab",
verbatimTextOutput("text2"),
style = sprintf(backgroundImageCSS, "https://images.plot.ly/language-icons/api-home/matlab-logo.png")
),
tabPanel(
"Tab2", value="second_tab",
verbatimTextOutput("text3"),
style = sprintf(backgroundImageCSS, "https://images.plot.ly/language-icons/api-home/python-logo.png")
)
))
server <- shinyServer(function(input, output, session){
output$text1 <- renderText("Trying to set up a first background image in this whole panel")
output$text2 <- renderText("Trying to set up a second background image in this whole panel")
output$text3 <- renderText("Trying to set up a third background image in this whole panel")
})
shinyApp(ui, server)
When using local images store them into a www folder (subdirectory of your app folder) or use addResourcePath to add the images as static resources to Shiny's web server,
Also see this related answer.
Related
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)
I have the following code that makes a simple shiny app.
```
library(shinydashboard)
library(shiny)
ui <- dashboardPage(
dashboardHeader(title = tags$img(src='https://cdn.vox-cdn.com/thumbor/Ous3VQj1sn4tvb3H13rIu8eGoZs=/0x0:2012x1341/1400x788/filters:focal(0x0:2012x1341):format(jpeg)/cdn.vox-cdn.com/uploads/chorus_image/image/47070706/google2.0.0.jpg', height = '60', width ='100')),
dashboardSidebar(
sidebarMenuOutput("menu")
),
dashboardBody()
)
server <- function(input, output) {
output$menu <- renderMenu({
sidebarMenu(
menuItem("Overview", icon = icon("tachometer"))
)
})
}
shinyApp(ui, server)
```
And the image is outputted on top of the menu to the right, but my goal would be to have the image be more in the middle of the dashboard. I know the menu shifts the navabr a bit but I would like to keep it as center as possible.
But my desired output would be like this. I made a sample with paint. Is it possible to still have some text or if a reference can be posted where I can learn more about the dashboard header function I would appreciate it.
Here you go
There is no way you can add the image to the header part on the right side with the function from shinydashboard, but let's have fun with the latest htmltools by injecting styles and tags into the header.
library(shinydashboard)
library(shiny)
header_img <- tags$img(
src='https://cdn.vox-cdn.com/thumbor/Ous3VQj1sn4tvb3H13rIu8eGoZs=/0x0:2012x1341/1400x788/filters:focal(0x0:2012x1341):format(jpeg)/cdn.vox-cdn.com/uploads/chorus_image/image/47070706/google2.0.0.jpg',
style = 'height: 50px; width: 100px; position: absolute; left: 50%; transform: translateX(-50%);'
)
header <- htmltools::tagQuery(dashboardHeader(title = ""))
header <- header$
addAttrs(style = "position: relative")$ # add some styles to the header
find(".navbar.navbar-static-top")$ # find the header right side
append(header_img)$ # inject our img
allTags()
ui <- dashboardPage(
header,
dashboardSidebar(
sidebarMenuOutput("menu")
),
dashboardBody()
)
server <- function(input, output) {
output$menu <- renderMenu({
sidebarMenu(
menuItem("Overview", icon = icon("tachometer"))
)
})
}
shinyApp(ui, server)
The img is placed on the center of right side header, not the center of the entire header length. If you want to adjust to the center of the whole length, try to change translateX(-50%) of the img to a number you like.
Is it possible to put all tabPanels in a row below the title of a navbarPage? In other words, I would like to keep the appearance of the navbarPage but on two rows: the title on the first one, and the tabPanels on the second. This would allow to "isolate" the title by keeping it on a single row.
library(shiny)
ui <- navbarPage(
title = "some title",
tabPanel("first tab"),
tabPanel("second tab")
)
server <- function(input, output, session) {}
shinyApp(ui, server)
Note that this doesn't have to be a navbarPage. Any UI that could do that is accepted but it has to have the appearance of a navbarPage (no space between the rows, etc.). Hope this is clear enough.
Also asked on RStudio Community
You can force the title to have 100% width via CSS, thereby moving the tabPanels below it:
library(shiny)
ui <- navbarPage(
title = "some title",
tabPanel("first tab"),
tabPanel("second tab"),
tags$style(HTML(".navbar-header { width:100% }
.navbar-brand { width: 100%; text-align: center }")) # center text
)
server <- function(input, output, session) {}
shinyApp(ui, server)
I have a problem with shiny tabs. I want to create a navigation page with two tabs. Right to them, I would like to insert some user's login details. There is no option "text" or other to insert a text in the navbarPage. But I created an additionnal tab instead:
library(shiny)
runApp(list(
ui = navbarPage(
title="My App",
tabPanel("tab1 title"),
tabPanel("tab2 title"),
tabPanel("User: Madzia")),
server = function(input, output) { }
))
It is OK like this, but I do not want the third tab to be "selectible": I want it to be disabled, so that we cannot click on it - the same as on "My App" text. Do you have any idea about how to handle this problem?
Thank you! Best, Madzia
You can achieve disabling a tab with a tiny bit of javascript. I have an example of how to hide a tab (not disable) in recent blog post, you can see the code for that here. I modified that code a bit for disabling instead.
This code is hacky because it was done in 2 minutes but will work for a basic use case
library(shiny)
library(shinyjs)
jscode <- '
shinyjs.init = function() {
$(".nav").on("click", ".disabled", function (e) {
e.preventDefault();
return false;
});
}
'
css <- '
.disabled {
background: #eee !important;
cursor: default !important;
color: black !important;
}
'
shinyApp(
ui = fluidPage(
useShinyjs(),
extendShinyjs(text = jscode, functions = "init"),
tags$style(css),
checkboxInput("foo", "Disable tab2", FALSE),
tabsetPanel(
id = "navbar",
tabPanel(title = "tab1",
value = "tab1",
h1("Tab 1")
),
tabPanel(title = "tab2",
value = "tab2",
h1("Tab 2")
),
tabPanel(title = "tab3",
value = "tab3",
h1("Tab 3")
)
)
),
server = function(input, output) {
observe({
toggleClass(condition = input$foo,
class = "disabled",
selector = "#navbar li a[data-value=tab2]")
})
}
)
Edit I didn't fully read the question when I posted my answer, I just saw that you wanted a way to disable a tab and that was my answer. Your specific usecase (creating a tab only to show the name of a user) is a bit strange, but I suppose this will still work...
I would like to keep my previous answer in existence because it may be useful for someone in the future who wants to know how to disable a tab.
But for this specific problem, disabling the tab is not the correct approach. It makes more sense to simply add text to the tab (as Valter pointed out in a comment). If you look at the documentation for bootstrap, it says you can add text into the navbar by adding an html element with class navbar-text. I experimented with the HTML a little bit to figure out exactly where this needs to be done, and created a little function that will wrap around navbarPage() to allow you to add text to it.
Here's an example:
library(shiny)
navbarPageWithText <- function(..., text) {
navbar <- navbarPage(...)
textEl <- tags$p(class = "navbar-text", text)
navbar[[3]][[1]]$children[[1]] <- htmltools::tagAppendChild(
navbar[[3]][[1]]$children[[1]], textEl)
navbar
}
ui <- navbarPageWithText(
"Test app",
tabPanel("tab1", "tab 1"),
tabPanel("tab2", "tab 2"),
text = "User: Dean"
)
server <- function(input, output, session) {
}
shinyApp(ui = ui, server = server)
I am writing an app and I want the image in the sidebarPanel to be just a bit bigger than the image I put inside it. As the window gets smaller or larger, so does the sidebar, but the image stays static. How do I fix this problem? Is there a way to get the sidebar length or is there a better way to render images?
ui.R
library(shiny)
shinyUI(bootstrapPage(
# Application title
titlePanel("Sidebar Image App"),
sidebarPanel(
imageOutput("image", height = "auto")
)
))
server.R
library(shiny)
shinyServer(function(input, output, session) {
output$image <- renderImage({
return(list(
src = "one.png",
contentType = "image/png",
height = 185,
alt = "Face"
))
})
})
You can style the image using css tag as below:
shinyUI(bootstrapPage(
titlePanel("Sidebar Image App"),
tags$head(tags$style(
type="text/css",
"#image img {max-width: 100%; width: 100%; height: auto}"
)),
sidebarPanel(
imageOutput("image")
)
)),
where css id selector (here #image) should correspond to the outputId of the imageOutput.