shinydashboard header dropdown add group links - html

I want to put multiple links within a dropdown menu in the header panel, but now I can only create it with a flat horizonal layout through tags$li, while I want a vertical grouped dropdown menu.
A minimal repeatable code is as below, I means I want to put the linkA and linkB under grouplinkAB, and users can open one of them in a new window. It may be achieved with dropdownMenu(type='notifications',...) as in the code, but I do not know where to put the group name of "grouplinkAB", and which can not open a new window when clicking on the link, also I have to hide the text "You have 2 notifications", so I want to achieve it with tags$li and tags$ul, but I have little knowledge on HTML, any help will be appreciated.
library(shinydashboard)
library(shiny)
runApp(
shinyApp(
ui = shinyUI(
dashboardPage(
dashboardHeader(title='Reporting Dashboard',
tags$li(class="dropdown",tags$a("grouplinkAB",href="http://stackoverflow.com/", target="_blank")),
tags$li(class="dropdown",tags$a("linkA",href="http://stackoverflow.com/", target="_blank")),
tags$li(class="dropdown",tags$a("linkB",href="http://stackoverflow.com/", target="_blank")),
dropdownMenu(type='notifications',
notificationItem(text='linkA',href="http://stackoverflow.com/"),
notificationItem(text='linkB',href="http://stackoverflow.com/")
)
),
dashboardSidebar(),
dashboardBody()
)
),
server = function(input, output){}
), launch.browser = TRUE
)

Ok, I saw a similar request about a year ago, but didn't look much deeper. This time I tried to get your code to work and couldn't then I looked at the dropdownMenu code and saw it simply wasn't setup to handle this, but could be modified to do so fairly easily.
I choose not to do that though, instead I created a new version of dropdownMenu specialized to do just this.
Here is the code:
library(shinydashboard)
dropdownHack <- function (...,badgeStatus = NULL, .list = NULL,menuname=NULL)
{
if (!is.null(badgeStatus)){
shinydashboard:::validateStatus(badgeStatus)
}
items <- c(list(...), .list)
lapply(items, shinydashboard:::tagAssert, type = "li")
dropdownClass <- paste0("dropdown ", "text-menu")
numItems <- length(items)
if (is.null(badgeStatus)) {
badge <- NULL
}
else {
badge <- span(class = paste0("label label-", badgeStatus), numItems)
}
tags$li(class = dropdownClass, a( href="#", class="dropdown-toggle",
`data-toggle`="dropdown", menuname, badge),
tags$ul(class = "dropdown-menu", items )
)
}
menuitemHack <- function(text,href){
notificationItem(text=text,href=href,icon=shiny::icon("rocket") )
}
runApp(
shinyApp(
ui = shinyUI(
dashboardPage(
dashboardHeader(title='Reporting Dashboard',
dropdownHack(menuname="GroupAB",
menuitemHack(text='linkA',href="http://stackoverflow.com/"),
menuitemHack(text='linkB',href="http://stackoverflow.com/")
),
dropdownMenu(type='notifications',
notificationItem(text='linkA',href="http://stackoverflow.com/"),
notificationItem(text='linkB',href="http://stackoverflow.com/")
)
),
dashboardSidebar(),
dashboardBody()
)
),
server = function(input, output){}
), launch.browser = TRUE
)
And here is the result:
Notes:
It needs an icon, you can select any fontAwesome or Glyphicons, there is probably a blank one there somewhere if you want to have nothing.
I imagine it will break if the ShinyDashboard structure changes much, so keep that in mind.
Maybe the next version will support this option as well, it would just be a few lines of extra code.

Related

How can I render HTML content in an R Shiny Popify (ShinyBS) tooltip?

I'm building out a datatable in R Shiny and part of it will include tooltips unique to each cell. I've accomplished that, however, I seem to be unable to insert HTML content into the tooltip itself. In the example below, I'm inserting HTML content into a cell in the datatable, and then aim to insert that same content into a tooltip, but the HTML only renders in the datatable, and not in the tooltip.
I've played around with a few ideas but can't find any that work. I can get the HTML to appear (as text) in the tooltip by removing the HTML function, but then, obviously, it's escaped and is just text. I am able to bold text within the tooltip using tags$b(), however, I am hoping for a solution more similar to my example below as I have more complex HTML content I would like add to the tooltip beyond just text.
Any ideas? Thanks very much!
library(shiny)
library(shinyBS)
library(DT)
ui <- fluidPage(
bsTooltip('tbutton',''),
mainPanel(dataTableOutput('df'))
)
server <- function(input, output) {
df <- data.frame(A = c(1:5), B = c(LETTERS[1:5]))
output$df <- renderDataTable({
cell <- paste0('<svg width="30" height="30">',
'<text x="1%" y="75%" font-weight="bold" font-size="16" >B</text>',
'</svg>')
df[2,2] <- as.character(popify(tags$div(HTML(cell)),
title = 'Tooltip:',
placement = 'left',
content = paste0(tags$div(HTML(cell))),
trigger = c('hover', 'click')))
datatable(df, escape=FALSE)
})
}
shinyApp(ui = ui, server = server)
To attach a popover to a cell, you can use bsPopover if this cell has an id. To set an id to the cells, you can use the datatables option createdCell.
Then the HTML code works in the popover content, but not the SVG (or at least I didn't manage to make it work).
library(shiny)
library(shinyBS)
library(DT)
df <- data.frame(A = 1:5, B = LETTERS[1:5])
css <- "
.red {color: red;}
"
ui <- fluidPage(
tags$head(tags$style(HTML(css))),
mainPanel(
DTOutput('df'),
bsPopover(
id = "id2",
title = "test",
content = '<p class="red">TEST</p>'
)
)
)
server <- function(input, output) {
output$df <- renderDT({
datatable(
df,
options = list(
columnDefs = list(
list(
targets = 2,
createdCell = JS(
"function (td, cellData, rowData, row, col) {",
" $(td).attr('id', 'id' + (row+1));",
"}"
)
)
)
)
)
})
}
shinyApp(ui = ui, server = server)

Shiny tooltips / spsComps

My question is in regards to
Shiny: Add Popover to Column Name in Datatable, the package spsComps for using tooltips, when I remove the tooltip which is defined in the mainPanel, the tooltip on the datatable column also does not work anymore.
library(shiny)
library(spsComps)
library(DT)
library(dplyr)
# define the question button in a button since we need to uses multiple times
infoBtn <- function(id) {
actionButton(id,
label = "",
icon = icon("question"),
style = "info",
size = "extra-small",
class='btn action-button btn-info btn-xs shiny-bound-input'
)
}
ui <- fluidPage(
titlePanel('Making a Popover Work in DataTable'),
mainPanel(
fluidRow(dataTableOutput('myTable'))
)
)
server <- function(input, output, session) {
output$myTable <- DT::renderDataTable({
# construct the title and convert to text
hp_text <- tags$span(
"hp",
infoBtn('notWorking') %>%
bsPopover(title = "This one does not work",
content = "I'd like to give information about hp: it means horsepower. I want a popover, because my real example has lot's of text.",
placement = "top",
trigger = "hover")
) %>%
as.character()
# use !! and := to inject variable as text
datatable(mtcars %>% rename(!!hp_text:=hp),
rownames=TRUE,
selection='none',
escape=FALSE)
})
}
shinyApp(ui = ui, server = server)
However, when once a tooltip is displayed once in the UI, then it also works for the datatable (from #lz100)
library(shiny)
library(spsComps)
library(DT)
library(dplyr)
# define the question button in a button since we need to uses multiple times
infoBtn <- function(id) {
actionButton(id,
label = "",
icon = icon("question"),
style = "info",
size = "extra-small",
class='btn action-button btn-info btn-xs shiny-bound-input'
)
}
ui <- fluidPage(
titlePanel('Making a Popover Work in DataTable'),
mainPanel(
fluidRow(
#popover button
infoBtn('workingPop') %>%
bsPopover(title = "This Popover Works",
content = "It works very well",
placement = "right",
trigger = "hover"
)
),
fluidRow(dataTableOutput('myTable'))
)
)
server <- function(input, output, session) {
output$myTable <- DT::renderDataTable({
# construct the title and convert to text
hp_text <- tags$span(
"hp",
infoBtn('notWorking') %>%
bsPopover(title = "This one does not work",
content = "I'd like to give information about hp: it means horsepower. I want a popover, because my real example has lot's of text.",
placement = "top",
trigger = "hover")
) %>%
as.character()
# use !! and := to inject variable as text
datatable(mtcars %>% rename(!!hp_text:=hp),
rownames=TRUE,
selection='none',
escape=FALSE)
})
}
shinyApp(ui = ui, server = server)
Is this a bug? Or is there something I am missing?
Change this on your UI:
mainPanel(
fluidRow(dataTableOutput('myTable')),
spsDepend("pop-tip")
)
So here, we add spsDepend("pop-tip"). This means loading the dependent Javascript library when app starts. In therory, -v-, the dependency would be automatically added, users do not need to know this. However, in this case, you are using the renderDataTable function. This package does not know how to handle htmltools::htmlDependency, which is the mechanism how usually developers add JS dependencies for shiny apps.
In your case, if you only use it once in the renderDataTable, we need to manually add the dependency in UI by spsDepend. But like your second case, if it has been used at least once in the UI, the dependency is there, you don't need to worry.
You can see the question mark for the button is not working either. The same problem. renderDataTable does not know how to add the dependency for actionButton. So in general, I wouldn't call it a bug, but a feature DT package doesn't support yet.
For the question mark, even if is not a problem caused by spsComps, but we do have a solution from spsComps, adding the icon library:
mainPanel(
fluidRow(dataTableOutput('myTable')),
spsDepend("pop-tip"),
spsDepend("font-awesome")
)

Set individual color of multiple progress bars in Shiny

How would one go about setting the background color of multiple fileInput() progress bars in one fluidRow(). This is similar to the answer given here, however, this time it's just for multiple fileInput() objects. I want to do something like snippet below, but when I run this, instead of having the three individual colors, they are all the same color (#cfa646). (Disclaimer, my html knowledge is non-existent, so I just wanted to demonstrate the concept with the given snippet.)
library(shiny)
ui <- fluidPage(
fluidRow(column(4,
tags$head(tags$style(".progress-bar{background-color:#3c763d;}")),
fileInput("dataUpload_1","Label 1",width = "400px")),
column(4,
tags$head(tags$style(".progress-bar{background-color:#bf37a4;}")),
fileInput("dataUpload_2","Label 2",width = "400px")),
column(4,
tags$head(tags$style(".progress-bar{background-color:#cfa646;}")),
fileInput("dataUpload_3","Label 3",width = "400px")))
)
server <- function(input, output){
}
shinyApp(ui=ui, server=server)
Nice try, you are close, but as you mentioned, this does require some advanced CSS knowledge. Here is how:
:nth-of-type() selector
library(shiny)
ui <- fluidPage(
tags$head(tags$style(
'
.myfiles .col-sm-4:nth-of-type(1) .progress-bar {background-color:#3c763d;}
.myfiles .col-sm-4:nth-of-type(2) .progress-bar {background-color:#bf37a4;}
.myfiles .col-sm-4:nth-of-type(3) .progress-bar {background-color:#cfa646;}
'
)),
fluidRow(
class = "myfiles",
column(4, fileInput("dataUpload_1","Label 1",width = "400px")),
column(4, fileInput("dataUpload_2","Label 2",width = "400px")),
column(4, fileInput("dataUpload_3","Label 3",width = "400px"))
)
)
server <- function(input, output){}
shinyApp(ui=ui, server=server)

Multiple NavBars on Shiny Dashboard-- remove weird spacing

I am using multiple navbars on my shiny dashboard page because I plan to create a conditional filter based on which tab is selected. Can the space between the two nav bars be removed?
Also, can the space reserved for the title be removed? I've seen some similar questions on here but I am pretty bad with CSS, so if someone could show me exactly where I can edit my code, that would be awesome.
Code:
library(shiny)
library(shinydashboard)
library(data.table)
library(dplyr)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(width = 325,
uiOutput("filter")),
dashboardBody(
navbarPage(header="",title=NULL,id="trythis" ,
tabPanel("BigTab1",
navbarPage(title = NULL,id="firstbar",
tabPanel("SubTab1",
dataTableOutput("table1")),
tabPanel("SubTab2"))),
tabPanel("BigTab2",
navbarPage(title=NULL,id="secondbar",
tabPanel("SubTab3",
dataTableOutput("table2")),
tabPanel("SubTab4")))
)
)
)
server <- function(input, output){
output$table1<-renderDataTable({
data<-filter(mtcars,cyl %in% input$test)
data.table(data[,1:2])
},options = list(lengthMenu = c(5, 10, -1), pageLength = 5))
output$table2<-renderDataTable({
data<-filter(mtcars,cyl %in% input$test)
data.table(data[,1:2])
},options = list(lengthMenu = c(5, 10, -1), pageLength = 5))
output$filter<-renderUI({
if(input$trythis=="BigTab1"){
selectInput("test","Test",choices = c("4","6","8"),selected=c("4","6"),multiple = TRUE)
}else{
selectInput("test","Test",choices = c("4","6","8"),multiple = FALSE)
}
})
}
shinyApp(ui = ui, server = server)
I want to remove the red, more worried about the space between the bars than the others, but the title space on the navbar is also pretty bad when you make the window smaller. Thanks in advance for any help!

Align widget buttons on same line in Shiny

I'm having issues aligning two input widgets in Shiny.
Specifically, I can't seem to get a password input and an action button (generated using uiOutput()) to be bottom aligned in the same row.
My current approach offsets the two widgets:
when what I want is:
My code:
library(shiny)
ui <- fluidPage(
fluidRow(
column(width = 4,
passwordInput(inputId = "answer.pass", label = "", value = "",
placeholder = "Enter Password for Answer")
),
column(width = 2, offset = 0,
uiOutput("actionBut.out")
)
)
)
server <- function(input, output) {
output$actionBut.out <- renderUI({
actionButton("copyButton1","Copy Code")
})
}
shinyApp(ui = ui, server = server)
I've come across other SO posts and other sites that seem to have similar problems, but none of their solutions work for my example.
Bottom align a button in R shiny
Shiny R Button Alignment
UI: positioning widgets (UI elements) side by side [Google Groups]
Can anyone suggest a working solution? Thanks!