3

I have a long table with more than 100 pages. I need to add some functionality so that the user may type the number of page, for example 50, and go to this page easily. This problem arises with very long tables when it is necessary to open some page which is in the middle of the interval. In this case the user have to click several times on the 'Previous' or 'Next' button.

In the example below I can't open on one click 8'th page.

1]

if (interactive()) {
  library(shiny)
  library(DT)
  shinyApp(
    ui = fluidPage(fluidRow(column(12, DTOutput('tbl')))),
    server = function(input, output) {
      output$tbl = renderDT(
        iris, options = list(lengthChange = FALSE)
      )
    }
  )
}

iomedee
  • 381
  • 1
  • 14

2 Answers2

9
library(shiny)
library(DT)

shinyApp(
  ui = fluidPage(
    fluidRow(
      div(style = "display:inline-block;", 
          numericInput("page", "Go to page:", value = 1, min = 1)),
      div(style = "display:inline-block;", 
          actionButton("gotopage", "Go"))
    ),
    fluidRow(
      column(12, DTOutput('tbl'))
    )
  ),
  server = function(input, output) {
    output$tbl = renderDT({
      datatable(
        iris, 
        callback = JS(c(
          "$('#gotopage').on('click', function(){",
          "  var page = parseInt($('#page').val())-1;",
          "  table.page(page).draw('page');",
          "});"
        ))
      )
    })
  }
)

enter image description here


Another option:

library(shiny)
library(DT)

shinyApp(
  ui = fluidPage(
    tags$head(tags$style(".pagination {float: right;}")),
    fluidRow(
      div(id="pagination", 
          div(style = "display:inline-block;", 
              tags$a(id = "first", style = "cursor: pointer;", "First")),
          div(style = "display:inline-block;", 
              tags$a(id = "previous", style = "cursor: pointer;", " Previous")),
          div(style = "display:inline-block;", 
              tags$input(id="page", type="number", class="input-sm", value="1", min="1")
          ),
          div(style = "display:inline-block;", 
              tags$span(id = "of")),
          div(style = "display:inline-block;", 
              tags$a(id = "next", style = "cursor: pointer;", "Next ")),
          div(style = "display:inline-block;", 
              tags$a(id = "last", style = "cursor: pointer;", "Last"))
      )
    ),
    fluidRow(
      column(12, DTOutput('tbl'))
    )
  ),
  server = function(input, output) {
    output$tbl = renderDT({
      datatable(
        iris, options = list(
          dom = "lfrti<'pagination'>", 
          initComplete = JS(c(
            "function(settings, json){",
            "  var table = settings.oInstance.api();",
            "  var pageinfo = table.page.info();",
            "  $('#of').text('of ' + pageinfo.pages);",
            "}"
          ))
        ),
        callback = JS(c(
          "$('div.pagination').append($('#pagination'));",
          "$('#first').on('click', function(){", 
          "  table.page('first').draw('page');",
          "  $('#page').val(1);",
          "});",
          "$('#previous').on('click', function(){", 
          "  table.page('previous').draw('page');",
          "  $('#page').val(table.page.info().page + 1);",
          "});",
          "$('#next').on('click', function(){", 
          "  table.page('next').draw('page');",
          "  $('#page').val(table.page.info().page + 1);",
          "});",
          "$('#last').on('click', function(){", 
          "  table.page('last').draw('page');",
          "  $('#page').val(table.page.info().pages);",
          "});",
          "$('#page').on('change', function(){",
          "  var page = parseInt($('#page').val());",
          "  if(!isNaN(page)){ table.page(page-1).draw('page'); }",
          "});"
        ))
      )
    })
  }
)

enter image description here

Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
  • I love your solution. I hoped that there is some inside option in `DT` which allows to type the number of page inside the pagination control. I looked through the official documentation but still didn't find anything https://datatables.net/examples/basic_init/alt_pagination.html – iomedee Jun 28 '19 at 17:11
  • @iomedee I think there's a plugin which does that (Pagination input) but currently it does not work with Datatables 1.10.x. It is demonstrated here: https://jsfiddle.net/qammar/ad4t12r8/2/ – Stéphane Laurent Jun 28 '19 at 17:31
  • @iomedee See my edit. This method replaces the pagination controls. – Stéphane Laurent Jun 28 '19 at 18:23
  • You are amazing! – iomedee Jun 29 '19 at 20:16
0

I want to share my own experience trying to find the DT implementation of pagingType: "input" as demonstrated at https://jsfiddle.net/qammar/ad4t12r8/2/

Fortunately, when browsing at this official website, they explain how to make use of plugins. It turns out there are some plugins available for the DT interface, one being the pagingType: "input" option.

Following the example given on their website, I was able to implent it in my project as follows:

DT::datatable(
 plugins = "input",
 options = list(
   pagingType = "input"
   )
 )

You can see the solution for my current app (sorry for the poor quality) which is: https://i.stack.imgur.com/3PEUL.gif

The code below shows a generic example:

library(shiny)
library(DT)

shinyApp(
  ui = fluidPage(
    fluidRow(
      column(12, DTOutput('tbl'))
    )
  ),
  server = function(input, output) {
    output$tbl = renderDT({
      datatable(
        iris,
        plugins = "input",
        options = list(
          pagingType = "input"
        )
      )
    })
  }
)

Nevertheless, the top answer is pure crack!

Isaangjim
  • 1
  • 2