我如何使用 shinyjs 来识别选项卡是否在 shiny 中处于活动状态?

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

使用 shinymaterial 包,我试图检查观察者中的选项卡是否处于活动状态并“做某事”,即下面示例中的 print("Hello")shinymaterial::material_tabs() 中的选项卡没有与之关联的闪亮 inputId,如果选项卡打开,则只有一个带有 class = "active" 的 href。

以下是我尝试使用 shinyjs 包的微弱尝试:

代表:


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)

活动选项卡更改时可能触发了一个事件,但我不熟悉这个包,我不知道。

下面是一个使用 MutationObserver 的解决方案(它不使用 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)