6

Here is how my noUiSlider looks like:

enter image description here

I would like to format the tick labels as: 1000 -> 1K, 900000 -> 900K, 5000000 -> 5M, etc; i.e. abbreviating the number with the appropriate SI symbol.

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
  
  tags$br(),
  
  noUiSliderInput(
    inputId = "noui", 
    label = "Slider vertical:",
    value =  50,
    orientation = "vertical",
    range = list("min" = list(0),
                 "25%" = list(1000, 500),
                 "50%" = list(10000, 50000),
                 "75%" = list(4000000, 500000),
                 "max" = list(10000000)),
    pips = list(
      mode = "values",
      values = list(0, 500, 1000, 900000, 5000000, 10000000),
      density = 4
    ),
    format = wNumbFormat(decimals = 0),
    width = "300px", height = "300px"
  ),
  verbatimTextOutput(outputId = "res")
  
)

server <- function(input, output, session) {
  
  output$res <- renderPrint(input$noui)
  
}

shinyApp(ui, server)
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225

1 Answers1

4

We need to set the pips option with JavaScript, to be able to pass a function to the format suboption:

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

abbreviateNumber <- '
const SI_SYMBOLS = ["", "k", "M", "G", "T", "P", "E"];

const abbreviateNumber = (number, minDigits, maxDigits) => {
    if (number === 0) return number;

    // determines SI symbol
    const tier = Math.floor(Math.log10(Math.abs(number)) / 3);

    // get suffix and determine scale
    const suffix = SI_SYMBOLS[tier];
    const scale = 10 ** (tier * 3);

    // scale the number
    const scaled = number / scale;

    // format number and add suffix
    return scaled.toLocaleString(undefined, {
        minimumFractionDigits: minDigits,
        maximumFractionDigits: maxDigits,
    }) + suffix;
};' # https://stackoverflow.com/a/65324090/1100107

js <- paste(
  "var slider = document.getElementById('noui').noUiSlider;",
  "slider.pips({",
  "  mode: 'values',",
  "  values: [0, 500, 1000, 900000, 5000000, 10000000],",
  "  density: 4,", 
  "  format: {", 
  "    to: function(x) {return abbreviateNumber(x);}",
  "  }",
  "});",
  sep = "\n"
)


ui <- fluidPage(
  
  useShinyjs(),
  
  tags$head(
    tags$script(HTML(abbreviateNumber))
  ),
  
  tags$br(),
  
  noUiSliderInput(
    inputId = "noui", 
    label = "Slider vertical:",
    value =  50,
    orientation = "vertical",
    range = list("min" = list(0),
                 "25%" = list(1000, 500),
                 "50%" = list(10000, 50000),
                 "75%" = list(4000000, 500000),
                 "max" = list(10000000)),
    format = wNumbFormat(decimals = 0),
    width = "300px", height = "300px"
  ),
  
  verbatimTextOutput(outputId = "res")
  
)

server <- function(input, output, session) {
  
  observeEvent(input$noui, {
    runjs(js)
  }, once = TRUE)
  
  output$res <- renderPrint(input$noui)
  
}

shinyApp(ui, server)

enter image description here

Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225