Shiny Tab scroller

Viewed 654

How can I add an arrow which lets me click and go through all my tabs.

I know I can add multiple tabs in one tabbox and click thorugh each tab to see each table.

But is there a way to design the UI such that I can scroll through entire page using arrows and see next tabbox

enter image description here

Want to change above to this

enter image description here

EDIT added reproducible code that uses modules and allows users to create as many tables based on slider

chartTableBoxUI <- function(id) {

  ns <- NS(id)


  div(
    tags$div(DTOutput(ns("chart"))),
    tags$div(DTOutput(ns("table")))

  )



}

chartTableBox <- function(input, output, session) {

  ns <- session$ns

  vals <- reactiveValues()

  observeEvent(input$chart_rows_selected,{

    vals$sel<- (input$chart_rows_selected)


  })

  output$chart <- renderDT({
    DT::datatable(
      mtcars,options = list(
        dom='t', pageLength = 5)

    )
  })

  output$table <- renderDT({


    DT::datatable(
      mtcars[vals$sel, 1:3],options = list(dom='t')
    )




  })

}

library(shiny)
library(shinydashboard)
library(tidyverse)
library(highcharter)
library(DT)
library(shinyjs)

ui <- fluidPage(

  fluidRow(
    tags$head(
      tags$link(rel="stylesheet", type="text/css",
                href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick-theme.css"),
      tags$link(rel="stylesheet", type="text/css",
                href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.css"),
      tags$script(type="text/javascript", 
                  src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.js"),
      tags$script(HTML(
        "$(document).ready(function(){
        $('#tables').slick({
        arrows: true,
        dots:true
        });
        });")),
    tags$style(HTML(
      "#tables .slick-prev {
      position:absolute;
      top:65px; 
      left:-100px;
      }
      #tables .slick-next {
      position:absolute;
      top:95px; 
      left:-100px;
      }
      .slick-prev:before, .slick-next:before { 
      color:red !important;
      }
      .content {
      margin: auto;
      padding: 20px;
      width: 80%;
      }"))
  ),



  sliderInput("dr", "Num of tables:",
              min = 0, max = 12,
              value = 2),
  uiOutput("tabs")
  #verbatimTextOutput("dr2")





    )

    )





server <- function(input, output, session) {
  for(i in 1:5)
    callModule(chartTableBox,i)

  output$tabs <- renderUI({
     num_tables<- input$dr


    tags$div(class="content",
             tags$div(id="tables",
                      lapply(1:num_tables,chartTableBoxUI)



             ))


  })





}

shinyApp(ui, server)
1 Answers

A solution without tabs, using the slick.js library. I don't know how to have the buttons side-by-side.

enter image description here

library(shiny)
library(DT)

ui <- fluidPage(
  tags$head(
    tags$link(rel="stylesheet", type="text/css",
              href="//cdn.jsdelivr.net/gh/kenwheeler/slick@1.8.1/slick/slick.css"),
    tags$script(type="text/javascript", 
                src="//cdn.jsdelivr.net/gh/kenwheeler/slick@1.8.1/slick/slick.min.js"),
    tags$script(HTML(
"$(document).ready(function(){
  $('#tables').slick({
    // put options here
  });
});"))
  ),
  sidebarLayout(
    sidebarPanel(
      ####
    ),

    mainPanel(
      tags$div(id="tables", 
               tags$div(DTOutput("table1")),
               tags$div(DTOutput("table2"))
      )
    )
  )
)

server <- function(input, output) {

  output$table1 <- renderDT({
    datatable(iris)
  })
  output$table2 <- renderDT({
    datatable(mtcars)
  })

}

shinyApp(ui = ui, server = server)

EDIT

I've finally managed to get grouped Previous/Next buttons:

enter image description here

library(shiny)
library(DT)

ui <- fluidPage(
  tags$head(
    tags$link(rel="stylesheet", type="text/css",
              href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick-theme.css"),
    tags$link(rel="stylesheet", type="text/css",
              href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.css"),
    tags$script(type="text/javascript", 
                src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.js"),
    tags$script(HTML(
"$(document).ready(function(){
  $('#tables').slick({
    arrows: true,
    dots:true
  });
});")),
    tags$style(HTML(
"#tables .slick-prev {
    position:absolute;
  top:65px; 
  left:-100px;
}
#tables .slick-next {
  position:absolute;
  top:95px; 
  left:-100px;
}
.slick-prev:before, .slick-next:before { 
    color:red !important;
}
.content {
    margin: auto;
    padding: 20px;
    width: 80%;
}"))
  ),
  sidebarLayout(
    sidebarPanel(
      ####
    ),

    mainPanel(
      tags$div(class="content",
        tags$div(id="tables", 
                 tags$div(DTOutput("table1")),
                 tags$div(DTOutput("table2"))
        )
      )
    )
  )
)

server <- function(input, output) {

  output$table1 <- renderDT({
    datatable(iris)
  })
  output$table2 <- renderDT({
    datatable(mtcars)
  })

}

shinyApp(ui = ui, server = server)

EDIT 2

Regarding your Edit, you can remove the tags$script(HTML(.... from tags$head and do:

  output$tabs <- renderUI({
    num_tables<- input$dr
    tagList(
      tags$div(class="content",
               tags$div(id="tables",
                        lapply(1:num_tables,chartTableBoxUI)
               )),
      singleton(tags$script(HTML(
        "$(document).ready(function(){
        $('#tables').slick({
        arrows: true,
        dots:true
        });
        });")))
    )
  })
Related