How do I use shinyjs to identify if tab is active in shiny?

703 Views Asked by At

Using the shinymaterial package, I'm attempting to check if a tab is active in an observer and "do something" i.e. print("Hello") in below example. The tabs in shinymaterial::material_tabs() do not have a shiny inputId associated with them, simply an href with class = "active" if the tab is open.

Below is my feeble attempt of trying this with the shinyjs package:

Reprex:


ui <- material_page(
  useShinyjs(),
  title = NULL,

  # Define tabs
  material_tabs(
    tabs = c(
      "First Tab" = "first_tab",
      "Second Tab" = "second_tab"
    )
  ),
  # Define tab content
  material_tab_content(
    tab_id = "first_tab",
    tags$h1("First Tab Content")
  ),
  material_tab_content(
    tab_id = "second_tab",
    tags$h1("Second Tab Content")
  )
)

server <- function(input, output, session) {
  
  #Below does not work
  # observe({
  #   if(session$sendCustomMessage(type = "shinymaterialJS", "$('li.tab a.active[href$=\"#second_tab\"]')")){
  #     print("Hello")
  #   }
  #   
  # })
}
shinyApp(ui = ui, server = server)
1

There are 1 best solutions below

0
On BEST ANSWER

There's probably an event triggered when the active tab changes but I'm not familiar with this package and I don't know.

Below is a solution using a MutationObserver (it does not use shinyjs).

library(shiny)
library(shinymaterial)

js <- "
$(document).on('shiny:connected', function() {
  var elem = $('ul.tabs')[0];
  // create an observer instance
  var observer = new MutationObserver(function(mutations) {
    for(var i = 0; i < mutations.length; i++) {
      var mutation = mutations[i];
      if(mutation.type === 'attributes' && mutation.attributeName === 'class') {
        var target = mutation.target;
        if(target.nodeName === 'A' && target.className === 'active') {
          var activeTab = target.getAttribute('href');
          Shiny.setInputValue('activeTab', activeTab);
        }
      }
    }
  });
  // configuration of the observer
  var config = {childList: false, subtree: true, attributes: true};
  // observe element
  observer.observe(elem, config);
})
"

ui <- material_page(

  tags$head(tags$script(HTML(js))),
  
  title = NULL,
  
  # Define tabs
  material_tabs(
    tabs = c(
      "First Tab" = "first_tab",
      "Second Tab" = "second_tab"
    )
  ),
  # Define tab content
  material_tab_content(
    tab_id = "first_tab",
    tags$h1("First Tab Content")
  ),
  material_tab_content(
    tab_id = "second_tab",
    tags$h1("Second Tab Content")
  )
)

server <- function(input, output, session) {
  observeEvent(input[["activeTab"]], 
    showNotification(
      tags$strong(paste0("Active tab: ", input[["activeTab"]])),
      type = "message"
    )
  )  
}

shinyApp(ui = ui, server = server)

enter image description here