jcoder
jcoder

Reputation: 15

JS in Highcharter (R) not invoked upon subsequent UI input change (Shiny)

This is my first post, but long time stack overflow lurker. I have been trying to invoke some Javascript in the Highcharter plot options for a mouseOver or click event when rendering a highchart map in R Shiny. The Javascript works when the app first launches, but when the user switches inputs in the UI to update the map, the Javascript I've written no longer works. The purpose of this JS is to, upon clicking on a state in the map, highlight the state in red. Reproducible example below:

##PACKAGES
library(shiny)
library(shinyWidgets)
library(shinyjs)
library(dplyr)
library(tidyverse)
library(albersusa)
library(highcharter)
library(usdata)

states <- data.frame(
  name  = rep(state.abb,4),
  metric = c(rep("YES",100),rep("NO",100)),
  value  = sample(100:5000,200)
)

ui <- fluidPage(
  
  tags$script(src = "https://code.highcharts.com/mapdata/countries/us/us-all.js"),
  
  fluidRow(
    radioButtons(inputId = "toggle",label="toggle it", 
                 choices = c("YES","NO")),
    column(width=5,highchartOutput("map1"))
    )
  )

server <- function(input, output, session) {
  
  #create rate change
  df1_num<- reactive({
    states %>%
    filter(metric == input$toggle) %>%
    group_by(name) %>%
    mutate(
      first = dplyr::first(value),
      last = dplyr::last(value)
    ) %>%
    distinct(metric,name,first,last) %>%
    mutate(
      #increase/decrease rate change
      rate  = round(((last-first)/first)*100,1),
    )
  })
  
  output$map1 <- renderHighchart({
    #US map of percent change in population trends
    hcmap("countries/us/us-all",
          data   = df1_num(),
          joinBy = c("hc-a2","name"),
          value  = "rate",
          borderColor = "#8d8d8d",
          nullColor = "#D3D3D3",
          download_map_data = FALSE
    ) %>%
      hc_plotOptions(series = list(
        point = list(
          events = list(
            click = JS("function() {
                       let currentY = this.name
                       charts = Highcharts.charts;
                       charts.forEach(function(chart, index) {
                       chart.series.forEach(function(series, seriesIndex) {
                       series.points.forEach(function(point, pointsIndex) {
                       if (point.name == currentY) {
                               point.setState('hover');
                               point.update({color:'red'})
                       }
                       })
                       });
                       });
        }")
          )
        )
      )
      )
  })

}

shinyApp(ui = ui, server = server)

As I stated, it works when the app first launches and a user clicks on any state in the map (or multiple states), but once the UI input changes, the JS no longer appears to work. Not sure if this is a bug in Highcharter, or my poor JS skills, or perhaps there is some kind of workaround in Shiny I'm missing.

Thanks!

Upvotes: 0

Views: 189

Answers (1)

Sebastian Hajdus
Sebastian Hajdus

Reputation: 1550

Here is an example of how to update the color point on the Highmaps inside point.events.

  plotOptions: {
    series: {
      point: {
        events: {
          click: function() {
            this.update({
              color: 'green'
            })
          }
        }
      }
    }
  },

DEMO: https://jsfiddle.net/BlackLabel/u6baodm7/

Upvotes: 1

Related Questions