R - Shiny Highcharter Helpers

Overview

Helper functions for Highcharter visualizations in Shiny applications. Includes:

  • Chart options configuration
  • Export button customization
  • Data label formatters (dollar, rate)
  • Tooltip formatters (number, rate, dollar, custom)

Code

Global Options

Configure Highcharter global options (thousands separator, rjson mode):

hc_opts <- function() {
  eval.parent({
    hcoptslang <- getOption("highcharter.lang")
    hcoptslang$thousandsSep <- ","
    options(highcharter.lang = hcoptslang)
    options(highcharter.rjon = TRUE)
  })
}

Export Button Options

Customizable export button with PDF, image, and CSV download options:

#' @importFrom htmlwidgets JS
hc_btn_options <- function() {
  list(
    contextButton = list(
      text = "Download",
      x = -25,
      menuItems = list(
        list(
          text = "Export to PDF",
          onclick = htmlwidgets::JS(
            "function () { this.exportChart({
              type: 'application/pdf'
            }); }"
          )
        ),
        list(
          text = "Export to Image",
          onclick = htmlwidgets::JS(
            "function () {
              this.exportChart(null, {
                chart: {
                  backgroundColor: '#FFFFFF'
                },
              });
            }"
          )
        ),
        list(
          textKey = 'downloadCSV',
          onclick = htmlwidgets::JS("function () {
            this.downloadCSV();
          }")
        )
      )
    )
  )
}

Data Label Formatters

Dollar Formatter

Formats values with K/M suffixes for large numbers:

#' @importFrom htmlwidgets JS
data_labels_dollar_formatter <- function() {
  htmlwidgets::JS(
    "function() {
      var y_val = this.y
      if (y_val > 1000000) {
        y_val = y_val / 1000000
        y_val = Math.round(y_val * 10) / 10
        y_val = y_val + 'M'
      } else if (y_val > 1000) {
        y_val = y_val / 1000
        y_val = Math.round(y_val * 10) / 10
        y_val = y_val + 'K'
      } else if (y_val > 1.1) {
        y_val = Math.round(y_val * 1000) / 1000
      } else {
        y_val = Math.round(y_val * 1000) / 1000
      }
      return y_val
    }"
  )
}

Rate Formatter

Formats decimal rates to 2 decimal places:

#' @importFrom htmlwidgets JS
data_labels_rate_formatter <- function() {
  htmlwidgets::JS(
    "function() {
      return Math.round(this.y * 100) / 100
    }"
  )
}

Tooltip Formatters

Simple Formatters

tooltip_formatter_number <- function() {
  '<span style="color:{point.color};font-weight:bold">\u25CF {series.name}: </span>{point.y:,.0f}<br/>'
}
 
tooltip_formatter_rate <- function() {
  '<span style="color:{point.color};font-weight:bold">\u25CF {series.name}: </span>{point.y:,.3f}<br/>'
}
 
tooltip_formatter_dollar <- function() {
  '<span style="color:{point.color};font-weight:bold">\u25CF {series.name}: </span>${point.y:,.0f}<br/>'
}

Advanced Multi-Series Formatter

Handles grouped data with custom metrics and K/M formatting:

#' @importFrom htmlwidgets JS
tooltip_formatter <- function() {
  htmlwidgets::JS("function() {
    var points = this.points
    var ys = points.map(function(el) {
      var out = null
      var y = el.y
      if (y > 1000000) {
        out = Math.round(y / 100000) / 10
        out = out.toLocaleString('en-US', {minimumFractionDigits: 1, maximumFractionDigits: 1})
        out = out + 'M'
      } else if (y > 1000) {
        out = Math.round(y / 100) / 10
        out = out.toLocaleString('en-US', {minimumFractionDigits: 1, maximumFractionDigits: 1})
        out = out + 'K'
      } else if (y > 2) {
        out = y.toLocaleString('en-US', {minimumFractionDigits: 0, maximumFractionDigits: 0})
      } else {
        out = y.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2})
      }
      return out
    })
 
    var html_out = '<b>' + this.x.name + ':</b><br/>'
    var last_metric = ''
 
    for (var i = 0; i < points.length; i++) {
      if (points[i].series.userOptions.my_metric !== last_metric) {
        html_out += '<b>' + points[i].series.userOptions.my_metric + ':</b><br/>'
        last_metric = points[i].series.userOptions.my_metric
      }
      html_out += '<span style=\"color:' + points[i].color + '\">\u25CF ' + 
                  points[i].series.userOptions.my_group + ': </span>' + ys[i] + '<br/>'
    }
 
    return html_out
  }")
}

Usage Example

library(highcharter)
 
# Apply global options
hc_opts()
 
# Create chart with helpers
highchart() |>
  hc_chart(type = "column") |>
  hc_add_series(data = c(1500000, 2300000, 1800000)) |>
  hc_plotOptions(
    series = list(
      dataLabels = list(
        enabled = TRUE,
        formatter = data_labels_dollar_formatter()
      )
    )
  ) |>
  hc_exporting(
    enabled = TRUE,
    buttons = hc_btn_options()
  )

See Also


(c) No Clocks, LLC | 2024