user51462
user51462

Reputation: 2022

R Shiny - Tracking the active tab in a tabset using JQuery

The app below contains two vertical tabsets. I would like to keep track of the active tab for each. I am using the following JQuery function to do this:

function getActiveTab(ns, id) {
  $('#' + ns + id).click(function() {

    var active = $(this).next('a.active').data('value');

    Shiny.setInputValue(ns + 'active_tab', active);

  });
}

However, it doesn't seem to return anything when I check the inspector in Chrome. I'm not sure if it's because I'm using the wrong selector (wasn't sure if it would be better to use children or find instead of next - I've tried all three to no avail.) or if the source is being loaded properly when the app starts up and was wondering if someone could shed some light?

Here is the full app:

library(shiny)
library(shinyWidgets)
library(shinyjs)

# MODULE 1 ----------------------------------------------------------------

modUI <- function(id) {

  ns <- NS(id)

  tagList(

    verticalTabsetPanel(
      id = ns('tabs'), contentWidth = 8, 
      verticalTabPanel(
        id = ns('tab1'),
        title = ns('tab1'), ''
      ),
      verticalTabPanel(
        id = ns('tab2'),
        title = ns('tab2'), ''
      )
    )
  )

}

modServer <- function(input, output, session) {
  ns = session$ns
  shinyjs::runjs(sprintf("getActiveTab(ns = '%s', id = '%s');", ns(''), 'tabs'))
  observe(print(input$active_tab))
}


# MAIN APP ----------------------------------------------------------------

shinyApp(
  ui = fluidPage(
    useShinyjs(),
    tags$head(tags$script("function getActiveTab(ns, id) {
  $('#' + ns + id).on('click', function(el) {

    var active_tab = el.find('a.active').data('value');

    Shiny.setInputValue(ns + 'active_tab', active_tab);

  });
}")),
    modUI('mod1'), modUI('mod2')
  ),

  server = function(input, output) {
    callModule(modServer, 'mod1')
    callModule(modServer, 'mod2')
  }
)

EDIT: The followed worked:

function getActiveTab(ns, id) {

  $('#' + ns + id).click(function() {

    var active = $(this).children('.active').data('value');

    Shiny.setInputValue(ns + 'active_tab', active);

  });
}

But why doesn't next('a.active') or children('a.active') work?

Upvotes: 0

Views: 536

Answers (1)

Tonio Liebrand
Tonio Liebrand

Reputation: 17689

You could do it in plain shiny:

Just use input$IDOFVERTTABSETPANEL. There should be similar questions, but probably not wrapped in a module.

Reproducible code:

library(shiny)

tabs<- function(id, label = "Counter") {
  ns <- NS(id)
  tagList(
    verticalTabsetPanel(id = ns("button"),
      verticalTabPanel(
        title = "Title 1", icon = icon("home", "fa-2x"),
        "Content panel 1"
      ),
      verticalTabPanel(
        title = "Title 2", icon = icon("map", "fa-2x"),
        "Content panel 2"
      )
    )
  )
}

tabTrack <- function(input, output, session) {
  observeEvent(input$button, {
    print(input$button)
  })
}

ui <- fluidPage(
  tabs("counter1", "Counter #1")
)

server <- function(input, output, session) {
  callModule(tabTrack, "counter1")
}

shinyApp(ui, server)

Upvotes: 1

Related Questions