Programmatically show/hide legend items in amCharts 4

The project includes a Line chart with a legend that are initialized in separate containers. Both components are created using a createFromConfig method.

<div ref="chartdiv" />
<div ref="legenddiv" />

My goal is to store toggled legend items as users switch between multiple tabs on the page. When users return to the tab with the chart, I want to programmatically toggle back these items.

The algorithm for achieving this involves:

  1. Storing toggled items
  2. Toggling previously toggled items when the chart is initiated by showing/hiding series, not legend items.

I have successfully stored labels by adding a click handler to legend items.

chart.value.legend.itemContainers.template.events.on('hit', (ev) => {
  toggledItems.push(ev.target.dataItem.name)
})

However, I am facing challenges with hiding previously toggled legend items. I have experimented with 'inited', 'hidden', 'shown' events as suggested in this question on stack overflow, but have not been successful.

// No reaction here ☹️
chart.value.series.template.events.on('hidden', () => {
  console.log('I am hidden')
})

I would appreciate guidance on how to proceed in the right direction.

Answer №1

Discovered a resolution that could potentially benefit others. Within our project, we implemented a Line chart component. I introduced a toggleSeries prop - acting as a v-model for managing toggled legend/series items, which stores strings (names). Therefore, when a user clicks on a legend item, the name of that item is stored and the toggleSeries v-model is updated accordingly. This setup allows for two-way binding; the chart can be initialized with predefined items in the toggleSeries array or items can be added externally to the Line component dynamically to update the chart.

// Function for toggling series in the chart's 'beforevalidated' hook
    const toggleSeries = (initial?: boolean) => {
      for (const currentSeries of chart.value.series.values) {
        if (toggledSeriesInternal.value.includes(currentSeries.dataFields.valueY)) {
          if (initial) {
            currentSeries.hidden = true
          }
          else {
            currentSeries.hide()
          }
        }
        else {
          if (initial) {
            currentSeries.hidden = false
          }
          else {
            currentSeries.show()
          }
        }
      }
    }

    // Function for toggling individual series items === adding/removing item names
    // from the 'toggledSeries' array
    const toggleSeriesItem = (itemName: string) => {
      const index = toggledSeriesInternal.value.findIndex(name => name === itemName)
      if (index === -1) {
        toggledSeriesInternal.value = [...toggledSeriesInternal.value, itemName]
      }
      else {
        const newToggledSeries = [...toggledSeriesInternal.value]
        newToggledSeries.splice(index, 1)
        toggledSeriesInternal.value = newToggledSeries
      }
    }

    chart.value.events.on('beforevalidated', () => {
      toggleSeries(true)
    })

    chart.value.legend.itemContainers.template.events.on('hit', (ev) => {
      toggleSeriesItem((ev.target.dataItem as am4core.DataItem & { name: string }).name)
    })

    watch(toggledSeriesInternal, () => {
      toggleSeries()
    }, {
      deep: true,
    })

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to calculate a cumulative total on a web form using javascript

Below is the structure of a form: <form id="calculator" action="#" method="get"> <h1>Cake Cost Estimator</h1> <h3>Round Cakes:</h3> <fieldset id="round"> <table> <tr> ...

Occasionally, the script tags in Next.js fail to load

https://i.stack.imgur.com/tSrIu.png An error message appears when the script tag fails to load. I have a total of 6 script tags in my code. These scripts are present in my code, but they do not consistently load. However, I can see them when ins ...

Tips for maintaining table elements in place using JavaScript

My goal is to keep the tags within the table fixed when printing. The code I've written functions correctly in View mode, however, when printed using JavaScript, if one of the columns is too large, the rest of the columns get displaced. I want all col ...

The dynamic combination of jCarousel, jQuery Accordion, and fade in effects

Take a look at this link www.aboud-creative.com/demos/mckinley3. You'll find a jQuery Accordion with jCarousel inside the "Developments" section. I have implemented a standard fadeIn function for the logo, accordion, and a stag on the bottom right to ...

Is it possible to utilize an imported function within the global router.beforeEach in Vue.js?

I'm attempting to utilize an imported function within my global router guard, but I encounter the following error message: getCurrentStage is not defined The getCurrentStage function is imported from shops.js This is what shop.js looks like: import ...

How can you trigger an event when a table cell is selected and a key is pressed?

In my project, I have some td elements with a class name assigned to them. My goal is to trigger a pop-up window when one of these td elements is in focus and the F9 key is pressed. Here's what I've attempted so far: $(document.body).keypress(fu ...

Using the forEach method, we can create multiple buttons in ReactJS and also access the onClick handler

I have a button with both the label and onClick properties. Additionally, I have an array containing the values I need to assign to the label property. Here is the code snippet: render(){ {tabel_soal.forEach(function (item, index) { <Ra ...

Is it possible to successfully pass a parameter from a servlet to a JavaScript function, but encounter issues when trying to view the database

In my view servlet, I am displaying user data from the database in a table. Each row of the table has buttons that allow users to change the cells in that row to text boxes. The issue I am encountering is that when I retrieve the data and loop through to ...

Using jQuery to target form elements that have a specific class assigned to them

I am facing an issue with targeting input fields within a specific form on a page. The form has a certain class, let's say "has-error," and I want to remove this class from all the input fields in that form. I attempted the following code snippet: t ...

When using the GET method to load a PHP file via AJAX, the page may not display certain jQuery plugins even after the file

Hello, I am a beginner learning AJAX and JQuery. Maybe this is a silly question, but please bear with me. I am trying to dynamically show data without refreshing the page using AJAX. I have a function loaded in the body tag which handles this. Everything ...

Ways to conceal an animated gif once it has been downloaded?

Is it possible to have an animated gif image vanish once server-side Java code runs and the client receives an HTTP Response from the webserver without relying on Ajax? I am currently utilizing the following Struts2 submit button: <s:submit value="sho ...

The timing of jQuery's .load function appears to be off, catching us by surprise

My current challenge involves loading returned html from an .aspx page through AJAX, but facing a timing issue with a click event that needs to occur before executing some essential tasks. Specifically, the process begins when a user types in a text field ...

Launch the sidebar window using jQuery

I've been attempting to create something similar to this. However, I'm having trouble replicating it exactly. What I've attempted I've managed to create a replica, but the issue is that the buttons are fixed. Could setting the left ...

Adding an item to an array in Angular 2 using JavaScript!

In my Angular2 form, I have a field that consists of an array of objects. I've successfully created a table with a Delete Row button for each row and an Add Row button using the push() and slice() methods in JavaScript. However, there's a major ...

Clearing local storage in JavaScript after a certain period of time

On my signup page, I have divided the process into 5 stages and am using the user ID to track which stage they are at by storing it in local storage. However, I would like to automatically remove the ID from local storage if users leave my website without ...

Why is the `node-config` configuration undefined within a TypeScript Jest environment?

I have a TypeScript module that is functional in both development and production environments. It utilizes https://github.com/lorenwest/node-config. When I attempt to import it into Jest for testing purposes, I encounter an error suggesting that the config ...

What is the best way to implement a subquery using EXISTS in Knex?

I'm currently facing challenges while constructing a query using knex, specifically when it comes to incorporating the 'WHERE' clause with the condition EXISTS (SELECT * FROM caregiver_patient WHERE patient_id IN (0,1)). Below is the origin ...

Issue with Firebase REST API filtering functionality not functioning as expected

Trying to master making rest calls using firebase Here's my attempt, but it's not returning any results: ('/cases.json?orderBy="case_status"&equalTo="live"') When I remove the ?orderBy="case_status"&equalTo="live"' I ...

Troubleshooting issues with AJAX script and JSON formatted data

Here is my complete script: <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/E ...

Tips for updating the value of an input text field in one HTML table according to a certain value entered in a different input text field located in another HTML table

I am working with an HTML table that consists of one row. Within this row, there are two TDs which each hold their own tables (each containing 10 rows with 10 input fields). My goal is to update the value of another corresponding text field based on change ...