Internal link between tabs to specific section in R Shiny app - r

I want to link to a specific content of another tabPanel within an R Shiny app. I've found plenty of advice on how to do the half part of it respectively: there are solutions how to use an anchor tag to link to content within a tabPanel...
SO: Create link to the other part of the Shiny app
... and on hwo to direct the link to another tabPanel:
SO: [Shiny]: Add link to another tabPanel in another tabPanel
SO: Linking to a tab or panel of a shiny app
SO: Externally link to specific tabPanel in Shiny App
Creating Internal Links - Defining Application Navigation by David Ruvolo
However, I need a combination of both: a link switching the view to another tabPanel at a specific location. In this app, based on mihasa's example, there are two tabPanels, where the first (Home) holds some text upon clicking that, the app should redirect to a section with the id visitme in Tab2.
library(shiny)
ui = shinyUI(
navbarPage("Header",
tabPanel("Home",
fluidPage(
"bring me to the desired point in Tab2")),
tabPanel("Tab2",
"Some Text inside Tab 2.",
div("This is a long div to visualize the redirection",
style = "background-color: gray;
height: 1000px;
width: 100px;"),
div(id = "visitme",
"This is the part where the redirection shall land."),
div("Another long div",
style = "background-color: gray;
height: 500px;
width: 100px;"))))
server = function(input, output, session){}
runApp(shinyApp(ui, server), launch.browser = TRUE)

Using K. Rohde's answer as starting point, their JavaScript was extended by a second argument for the given id and a command, that scrolls to it (document.getElementById(anchorName).scrollIntoView()), allows to move to a certain section within a given tabPanel after switching to it.
library(shiny)
ui = shinyUI(
navbarPage("Header",
tabPanel("Home",
tags$head(tags$script(HTML('
var fakeClick = function(tabName, anchorName) {
var dropdownList = document.getElementsByTagName("a");
for (var i = 0; i < dropdownList.length; i++) {
var link = dropdownList[i];
if(link.getAttribute("data-value") == tabName) {
link.click();
document.getElementById(anchorName).scrollIntoView({
behavior: "smooth"
});
};
}
};
'))),
fluidPage(
span("bring me to end of tab2",
onclick = "fakeClick('Tab2', 'visitme')"))),
tabPanel("Tab2",
"Some Text inside Tab 2.",
div("This is a long div to visualize the redirection",
style = "background-color: gray;
height: 1000px;
width: 100px;"),
div(id = "visitme",
"This is the part where the redirection shall land."),
div("Another long div",
style = "background-color: gray;
height: 1000px;
width: 100px;"))))
server = function(input, output, session){}
runApp(shinyApp(ui, server), launch.browser = TRUE)

Related

Add some italic text on the right side of the navbarPage in Rshiny

I am building a Shiny app where I want to add some italic text in the navbarPage at the right side. According to the question: Shiny NavBar add additional info I wrote the following code, but it doesn't work out for me:
This is some demo code I have now:
ui <- fluidPage(
navbarPage(theme = shinytheme("flatly"), collapsible = TRUE,
HTML('<a style="text-decoration:none;cursor:default;color:#FFFFFF;" class="active" href="#">Dashboard</a>'), id="nav",
navbarMenu('Graphs', icon = icon('chart-area'),
tabPanel('One country'),
tabPanel('Two countries')),
tabPanel('Tables'),
tags$script(HTML("var header = $('.navbar> .container-fluid');
header.append('<div style=\"float:right\"><h5>Some very important text</h5></div>');
console.log(header)"))
))
server <- function(input, output, session) {}
shinyApp(ui = ui, server = server)
This results in:
the following warning message: Warning message:
Navigation containers expect a collection of bslib::nav()/shiny::tabPanel()s and/or bslib::nav_menu()/shiny::navbarMenu()s. Consider using header or footer if you wish to place content above (or below) every panel's contents.
not the desired output. Because, the text is not visible, because it has the same colour as the background, the text is under the Dashboard, Graphs en tables text, but I want them to be on the same line. The text is not in italic.
Output now
This is what I want:
Desired output
After the answer from lz100 it looks very nice on a big screen, but the text is still under the Dashboard, Graphs en tables text. And when I change the format of the Rshiny dashboard to my very small laptopscreen, the output becomes likes this:
Output after answer from lz100
library(shiny)
library(shinythemes)
ui <- fluidPage(
navbarPage(theme = shinytheme("flatly"), collapsible = TRUE,
HTML('<a style="text-decoration:none;cursor:default;color:#FFFFFF;" class="active" href="#">Dashboard</a>'), id="nav",
navbarMenu('Graphs', icon = icon('chart-area'),
tabPanel('One country',
tags$script(HTML(
"
var header = $('.navbar> .container-fluid');
header.append('<div id=\"my-title\">Some very important text</div>');
")),
tags$style(HTML(
'
.navbar-collapse.collapse {display: inline-block !important;}
#my-title {
float:right;
display: flex;
color: white;
align-items: flex-end;
justify-content: flex-end;
height: 60px;
font-style: italic;
}
'
))
),
tabPanel('Two countries')),
tabPanel('Tables')
)
)
server <- function(input, output, session) {}
shinyApp(ui = ui, server = server)
The reason you have warnings is because you put tags$script under navbarPage. Not a big deal to me, but I relocate your script inside the first tabPanel, warnings are gone.
Some CSS and JS added to create your desired output
Search/Read here if you don't know how these CSS work: https://www.w3schools.com/css/default.asp

Weird behavior of selectizeInput

In the Shiny App below, I am facing a very strange behavior, where selectInput box slides downwards when I type something in this box. Also, the text inside selectInput box moves towards the right while I type in this box. I have spent a lot of time to find out the reason for this problem but could not figure it out. Can someone point out the mistake I am doing causing this strange behavior?
library(shiny)
library(shinydashboard)
library(highcharter)
siderbar <- dashboardSidebar(
sidebarMenu(
selectizeInput(inputId = "select_by", label = "Select by:", choices = NULL, multiple = FALSE, options = NULL)
)
)
body <- dashboardBody(
fluidRow(
tabBox(
side = "right",
selected = "Tab1",
tabPanel("Tab1", "Tab content 1", highchartOutput("tabset1Selected"))
)
),
)
shinyApp(
ui = dashboardPage(
dashboardHeader(title = "tabBoxes"),
siderbar,
body
),
server = function(input, output, session) {
selectedVal <- reactiveValues()
updateSelectizeInput(session, "select_by", choices = c(as.character(1:10000)), selected = 2, server = TRUE)
output$tabset1Selected <- renderHighchart({
selectedVal <- input$select_by
print(highcharts_demo())
})
}
)
We were on the right track. It has something to do with selectize.js updating the items from the server. You can verify that by setting the loadThrottle option to 5000. This option determines how long the widget waits "before requesting options from the server" (see the manual). Now you have to wait exactly 5 seconds and then the select widget flickers.
The issue seems to be caused by a CSS conflict. selectize.js adds a CSS class to the widget. If you remove that feature, the flicker goes away.
selectizeInput(inputId = "select_by", label = "Select by:",
choices = NULL, multiple = FALSE,
options = list(loadThrottle=200, loadingClass=""))
loadingClass sets a specific CSS class (default: 'loading') while loading data from the server. Purpose: to change how the widget looks and communicate to users that an update is in progress.
loadThrottle does not need to be set. It's default is 300. You can set it to any value that suits your needs.
Details
highcharter defines it's own CSS class names loading with these specs:
.loading {
margin-top: 10em;
text-align: center;
color: gray;
}
That is the reason for the CSS conflict. The widget gets a top margin and it's content moved to the center, because the browser does not distinguish the source of the class. It only sees some CSS that fits and uses it. This image shows where you need to look:

change color actionButton Shiny R

i'm trying to figure out a way to get an actionButton to change color (and possibly other style elements as well.)
The objective is very general and I'll use this for many button responses throughout my complex shinyDashboard App. Simply said: if a button is clicked, or a specific element (i.e. inputslider) changes that is linked to a button, the button should change color.
I usually code my buttons in Shiny like this one:
actionButton(inputId= "RunFullModel", label =icon("tree-deciduous", lib = "glyphicon"),
style = "color: white;
background-color: #35e51d;
position: relative;
left: 3%;
height: 35px;
width: 35px;
text-align:center;
text-indent: -2px;
border-radius: 6px;
border-width: 2px")),
I've been browsing my ass off, but no luck to something that works.
I have been looking at shinyjs by #Dean Attali to do this, but I can only get it to work to change the background of the printed text as in the example below. The part using ToggleClass or AddClass doesn't work for actionButton("x", "y") it seems.
I've also tried to use updateActionButton from the shiny package itself, but this does not seem to allow style = "..." to be included in the command.
library(shiny)
library(shinyjs)
library(shinyBs)
if (interactive()) {
shinyApp(
ui = fluidPage(
useShinyjs(),
inlineCSS(list(.red = "background: red")),
inlineCSS(list(.blue = "style = 'background-color: blue'")),
actionButton("checkbox", "Make it red"),
bsButton("checkbox2", "Make me blue"),
p(id = "element", "Watch what happens to me")
),
server = function(input, output) {
observe({
toggleClass(id = "element", class = "red",
condition = input$checkbox)
})
observe({
toggleCssClass(id = "checkbox2", class = ".blue",
condition = input$checkbox)
})
}
)
}
The demo model of shinyjs is found here: http://deanattali.com/shinyjs/overview#demo and it looks as if the toggleClass works there for the button with id "btn" but there is no code example directly to be found, and the indirect example from another section of the shinyjs page doesn't seem to work.
Option 3 I tried to have the style = "background-color: ....read R variable" part access an R variable that contains the color name, i.e. mycolor <- "red", but that doesn't work either, and my knowledge of javascript is too limited to figure out how to make that work.
So, .... if anyone has an idea how to make the color switching work with shinyjs, or with another method that works with my button coded above, I would highly appreciate it, and grant you my eternal gratitude. (been stuck on this for weeks now with this issue)
Mark
p.s. i've looked into bsButtons as well but they are too limited for what I want with the default class options.
That should be doable in "pure" shiny:
Use renderUI() to create the button and insert conditions to check if the button was clicked already.
I decided to store the information (whether a button was clicked) within a reactiveVariable as you wrote that you plan to trigger the color change "if a button is clicked, or a specific element (i.e. inputslider) changes that is linked to a button". So you could also change the global$clicked from other inputs.
library(shiny)
shinyApp(
ui = fluidPage(
uiOutput("button")
),
server = function(input, output) {
global <- reactiveValues(clicked = FALSE)
observe({
if(length(input$RunFullModel)){
if(input$RunFullModel) global$clicked <- TRUE
}
})
output$button <- renderUI({
if(!is.null(input$RunFullModel) & global$clicked){
actionButton(inputId= "RunFullModel", label =icon("tree-deciduous", lib = "glyphicon"),
style = "color: white;
background-color: #35e51d;
position: relative;
left: 3%;
height: 35px;
width: 35px;
text-align:center;
text-indent: -2px;
border-radius: 6px;
border-width: 2px")
}else{
actionButton(inputId= "RunFullModel", label =icon("tree-deciduous", lib = "glyphicon"))
}
})
}
)

Rshiny - Disabling tabs / adding text to tabs

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)

R shiny: color fileInput button and progress bar

Is there a way to color fileInput button in R shiny? It looks like it is possible as shown here on this page on github. However I cannot find the code for this to be done.
This is the simple application that I would like to modify to have the button and progress bar colored red.
In ui.R:
library(shiny)
shinyUI(fluidPage(
titlePanel("Test"),
fileInput("Test","")
))
and server.R
library(shiny)
shinyServer(
function(input, output) {
}
)
Thanks for any advice.
You can use standard Bootstrap classes to style action buttons:
library(shiny)
shinyApp(
ui=shinyUI(bootstrapPage(
actionButton("infoButton", "Info", class="btn-info"),
actionButton("warningButton", "Warning", class="btn-warning"),
actionButton("successButton", "Success", class="btn-success"),
actionButton("dangerButton", "Danger", class="btn-danger"),
actionButton("defaultButton", "Default", class="btn-default"),
actionButton("primaryButton", "Primary", class="btn-primary")
)),
server=shinyServer(function(input, output, session){
})
)
Regarding file inputs as far as I know it is not possible without using CSS directly. Page you've linked is an opened pull-request and it doesn't look like it will be merged soon.
This answer provides a good description how to create fancy upload buttons with bootstrap. It should work just fine in Shiny as well.
CSS could be used in shiny to custom your fileInput widget !
Use the following code in order to color it in red.
NB - Any browser you're using to view the app should have developer tools that let you inspect elements and see styles applied to any element. You have to right click on the relevant element and choose inspect !
library(shiny)
ui <- fluidPage(
fileInput(inputId = "Test",label = ""),
tags$style("
.btn-file {
background-color:red;
border-color: red;
}
.progress-bar {
background-color: red;
}
")
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)

Resources