Link tabs in navbarPage


#1

Hello everyone,

What i would like to do, is to have a first page where people will select what they want, and then by clicking on it they will be directed to the relevant page.

I found a working code here :

I got rid of the sidebarLayout item since I don't need it and it does not change anything anyway. So, my code in the tab where i want to be transfered is :

tabPanel("HypothesisTesting", 
                                     HTML("<script>$('#HypothesisTesting').click(function() {
                                        tabs = $('.tabbable .nav.nav-tabs li')
                                          tabs.each(function() {
                                          $(this).removeClass('active')
                                          })
                                          $(tabs[1]).addClass('active')
                                          
                                          tabsContents = $('.tabbable .tab-content .tab-pane')
                                          tabsContents.each(function() {
                                          $(this).removeClass('active')
                                          })
                                          $(tabsContents[1]).addClass('active')
                                          
                                          $('#HypothesisTesting').trigger('change').trigger('shown');
                                          
                                          })</script>"), <rest of my code>

...

and the code where i want to place the link is :

                            tags$div(div(id="HypothesisTesting",tags$a("HypothesisTesting"))),

So far, it works. However, my problem now is that when i click on the "clickable title"( "HypothesisTesting" in this example), i am being transfered in the correct tab BUT not on the top of that, but exactly in the same position of the page that was my "clickable title". So, in other words, to which place of the tab i will be directed is dependent on which place of the tab i was when i clicked on the "clickable title".

Because I just found and used the above code and moreover because i am not familiar with HTML, excuse me if my question is simple or even silly...! :slight_smile:

Thanks,
John


#2

One line of JS that targets the vertical scroll position of the window should do the trick. Try adding the following code after the last line.

$(document).ready(function(){$(window).scrollTop(0);});

Hope that works!


#3

@dcruvolo Thanks for your reply!

This code made the trick! :smiley:

Really thanks!

John


#4

@dcruvolo ,

Sorry to bother you again, but i have another problem with this now...

This "clickable" item is being shown in all panels on top! ( see the screenshots). How can i keep it only where i want it to be and remove it from all other places? In the screenshots, in the first one is where i actually want it, but in the second where it shouldn't be shown...

Screenshot_3

Screenshot_4

Moreover, another problem i have is this: If i want to link to another tabPanel ( i have several major tabPanels with tabsetPanels inside them, see also the screenshot), for some reason i cannot... For instance, put a clickable item in the "Design for mice experiments" tab to trasfer me to "Fundamentals-Power" tab. Do I need to change something in the HTML script to take that into account ?


Thanks,

John


#5

Hi @Emperor3,

Sorry to hear you are still having troubles. I have a few thoughts on both issues.

The Lingering Link

If I understand the issue correctly, the link "Hypothesis Testing` appears on other tabs? This is puzzling, but I have a few ideas on how to debug this problem.

  1. What happens when you comment out the text block "more about sample size ad power calculations can be found..." on the tab "Statistics"? Does the text still appear in unwanted places?

  2. What happens when you comment out all text on the "others" tab? Does the stubborn link appear in the "hypothesis testing" tab?

  3. What happens when you comment out the entire tab "Statistics"? Is the text still there?

  4. What happens when you comment out the entire tab "Others"? Is the text still there?

  5. Are there any warnings in the js console? (i.e., Inspect Element)?

Perhaps there is some extra text? Another idea may be that a block of text is placed outside a tabPanel and the code is still structured properly that no errors were detected (the option I'm placing my money on). Without seeing the actual code, it's hard to say for sure. I hope this may point you in the right direction.

Internal Links

I may be able to offer a solution for this part. Every time a shiny app is launched, values for the href attribute in the <a> element(s) are regenerated. This makes traditional hyperlink calls <a href="#mytab">mytab</a> impossible. One way is to work with the attribute data-value which can be accessed via the argument value in tabPanel function.

By default, the value for argument title is automatically assigned to the argument value (see R reference page below). However, it might be useful to manually set the value to a shorter string. Using the screenshots above, for the tab "Paired t-test" you may want to write the value as "tab-t-test".

Next, add the following js function to the UI header. This function loops through all the values in the data-value to look for the desired tab (I adapted code from this SO post -- I'll update when I've found the link). When a match is found, to simulate a mouse click using link.click (this will advance the screen to the desired tab).

var customHref = function(tabName) {
	var dropdownList = document.getElementsByTagName( class="value">"a");
		for (var i = 0; i < dropdownList.length; i++) {
		    var link = dropdownList[i];
		    if(link.getAttribute("data-value") == tabName) {
			link.click();
		}
	}
};

You can either place this at the top of the UI or store in a separate file and load using includeScript or tags$script. For manually creating links, use the tag a() and instead of using href we will set an onclick event.

tabPanel(
    "Some content here.", 
    "More content",
     a("onclick"="customHref('mytab')","mytab"), 
    "More content"
)

To summarize you will need three things.

  1. The javascript function
  2. manually assign values to each tab
  3. manually set the target tab by assigning an onclick event

I've written up this method and posted a few example apps that may help you build the app using this approach. You can find them here. One known issue is that on smaller devices, the navigation bar will stay open after a link is clicked. I have a work around for single-page apps, but I've yet to figure out how to apply it to apps with many pages/tabs.

Hope that helps!

https://shiny.rstudio.com/reference/shiny/1.0.2/tabPanel.html

EDIT: I missed a couple of end quotes


#6

@dcruvolo, Ok first of all this is an amazing answer! Thanks for thaking the time to do that..

Now, i solved the first problem and it seems that you would be rich if you had placed your bet! Indeed, something was out of the tabPanel box...

For the second part, maybe i miss something... So, i created this new file, "func.js" which i placed in the WWW folder. Then, i load it using tags$script as is in your example. See also the screenshot to confirm that i did it correclty.

Also, let's say that from the first page i want to click the link and move to the tab "Fundamentals -Power". In the first screenshot you see the code. The first link is from earlier, i just added the a(..) line.

sssssss

And this is the code i have in the other tab..

Screenshot_6

The iink in the first page is shown but it is not clickable....I didn't understand if i have to keep the code i provided here in my first post and just add yours, or remove it entirely... I tried both( here you see the second), but no luck... The other chance is that i didn't load the function correctly...

Thanks again!!

Best,
John


#7

My apologies, @Emperor3. I forgot that quotes around onclick aren't necessary and that it's good practice to use tags$ for html elements. The code would look something like this:

tags$a(onclick="customHref('power')","Power")

Using the screenshot as a guide, the div with the id HypothesisTesting would be structured in the following way (no need to nest the div unless there are other elements and combine the two a elements).

tags$div(
    id = "hypothesisTesting",
    tags$a(onclick="customHref('power')","Power")
)

I hope this fixes the issue!


#8

Again nothing @dcruvolo...

The link does not get clickable...Is the javascript function correct(because i get a notice..) ? And is it wrong that i placed it in the WWW folder ? And again, do i still need the html code block each time or it is redundant after i included this javascript function ?

Screenshot_7

Finally, these ara my codes now( link from the first to the second)...
Screenshot_8


Screenshot_9

EDIT : I tried something else and i now i can see that something is odd...

I created 2 links in the first page, both linking to 2 tabs but within the same tabPanel. From the screenshot above, going from "Statistics" to "HypothesisTesting" and "Other" respectively. But, both of these links transfer me to the "HypoethesisTesting" tab...Then i kept only the link that goes to the tab "Others" and i am still directed to the tab "HypotehsisTesting"... I checked the namings and so, and all seem correct specified...

Thanks,
John


#9

Hello all,

This is an update on the issue of linking other pages and tabs in a shiny app. We took the discussion offline and recently solved the problem. I've also created a demo app for those who are interested in creating internal links to specific pages or tabs (a link is provided at the end).

Background

To make this work you will need three things.

1. Manually assign a value for each tab

tabPanel("My Tab Name", value = "tab-value", ...)

2. JS function

The following function loops through all a elements and looks for a matching tab name (as defined above). When a match is found, the code will simulate a mouse click using click(); (this will advance the screen to the desired tab).

Place this code in a new file and store it in the www directory.

var customHref = function(tabName) {
	var dropdownList = document.getElementsByTagName( class="value">"a");
		for (var i = 0; i < dropdownList.length; i++) {
		    var link = dropdownList[i];
		    if(link.getAttribute("data-value") == tabName) {
			link.click();
		}
	}
};

Load the file using includeScript or tags$script.

shinyUI(
    tagList(

        # head
        tags$head(
            tags$script("src"="func.js")
        ),

       # body
        ...
    )
)

3. Assign an onclick event for each navigation link.

The function customHref takes one input and that is the target location (the tab you want to go to). If you are using tabsetPanel with navbarPage and want to go to a specific tab on another page, make two calls to the function customHref. The first is to the page the tab is located on and the second is to the tab itself.

# nav to another page
tags$a("Go back to the 'Home' page.", onclick="customHref('page-home')")


# nav to a specific tab on another page
tags$a("Go to Page 2 Tab 2", onclick="customHref('page-2'); customHref('tab-2');")

Known Issues

On mobile devices, the navigation menu may remain open after a link is clicked. This seems to be a common issue with Bootstrap and can be corrected with a few lines of js (github/bootstrap/issues/12852).

Demo App

The demo shiny app can be found on github:

davidruvolo51/shinyAppTutorials/Internal-Links-Demo

Hope this helps!

:smile: