dreamRs / apexcharter

:bar_chart: R Htmlwidget for ApexCharts.js
https://dreamrs.github.io/apexcharter
Other
138 stars 15 forks source link

Adding Icons to the Labels in a Legend #67

Closed radovan-miletic closed 1 year ago

radovan-miletic commented 1 year ago

Hi Victor,

The labels in "donut" chart (which I very much appreciate) can be easily turned into additional filter with awesome set_input_click(). Following issue 50, in last few days I was trying to figure out how to add icon (or opacity, color, etc.) to the clicked label item in "donut" chart. I was unable to pass from adding icons to all labels (non-desired output):

````
my_data <- mtcars |> 
  dplyr::select(mpg, hp) |> 
  tibble::rownames_to_column("car") |> 
  dplyr::arrange(car)
my_chart <- apexcharter::apex(data = my_data, 
                              type = "donut", 
                              mapping = ggplot2::aes(x = car, y = hp), 
                              auto_update = FALSE) 
my_chart$dependencies <- htmltools::htmlDependencies(shiny::icon("check-square"))
my_chart |> apexcharter::ax_legend(position = "right", 
                                   formatter = htmlwidgets::JS("function(value) {
   return '<i class=\"fa fa-check-square\" aria-hidden=\"true\"></i>' + ' ' + value + '</span>';}"))
````

Output: apex

I'm wondering if it's possible to achieve desired output, maybe with JS onClick event? Any help would be greatly appreciated if possible. Thank you.

pvictor commented 1 year ago

Hello Radovan,

Glad you like those functionnalities ! 😄 No built-in way to do it I think, you have to use some CSS and JavaScript, here's an example for shiny :

library(apexcharter)
library(shiny)

ui <- fluidPage(
  # some CSS to style the clicked legend item (the one with class 'active')
  tags$style(
    ".apexcharts-legend-series.active {opacity: 0.5 !important;}",
    HTML(".apexcharts-legend-series.active > .apexcharts-legend-text > .my-icon {display: inline-block !important;}"),
    ".my-icon {display: none;}"
  ),
  # when legend item is clicked add class 'active' to it and remove to it for others
  tags$script(
    "$(document).on('click', '.apexcharts-legend-series', function(event) {
      $(this).siblings().removeClass('active');
      $(this).addClass('active');
    });"
  ),
  apexchartOutput("chart")
)

server <- function(input, output, session) {
  output$chart <- renderApexchart({
    my_data <- mtcars |> 
      dplyr::select(mpg, hp) |> 
      tibble::rownames_to_column("car") |> 
      dplyr::arrange(car)
    my_chart <- apexcharter::apex(data = my_data, 
                                  type = "donut", 
                                  mapping = ggplot2::aes(x = car, y = hp), 
                                  auto_update = FALSE) 
    my_chart$dependencies <- htmltools::htmlDependencies(shiny::icon("check-square"))
    my_chart |> apexcharter::ax_legend(position = "right", 
                                       formatter = htmlwidgets::JS("function(value) {
   return '<i class=\"fa fa-check-square my-icon\" aria-hidden=\"true\"></i>' + ' ' + value + '</span>';}")) # custom class to icon
  })
}

shinyApp(ui, server)

Let me know if you question about this.

Victor

radovan-miletic commented 1 year ago

This is almost exactly what I am looking for.
I'm wondering if it's possible to mark multiple choices instead of one at a time. Could we click on a legend, add class 'active' to it, and remove it clicking back on the same legend (deselect selected options)? In a way, it needs to be consistent with set_input_click(inputId = "id_click_multiple", multiple = TRUE).

Thank you very much for your time and attention, Victor.

pvictor commented 1 year ago

Sure, you can replace in javascript code :

$(this).siblings().removeClass('active');
$(this).addClass('active');

by :

 $(this).toggleClass('active');

like this it will add the class active to the legend item if not present and remove it if present.

radovan-miletic commented 1 year ago

Beautiful! Thank you for support.