Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hiding a line is not persistent with data changes #48

Open
pdonias opened this issue Nov 24, 2017 · 6 comments
Open

Hiding a line is not persistent with data changes #48

pdonias opened this issue Nov 24, 2017 · 6 comments
Labels

Comments

@pdonias
Copy link

pdonias commented Nov 24, 2017

I have 2 data sets:

const DATA1 = {
  series: [
    [0, 2],
    [1, 1]
  ]
}

const DATA2 = {
  series: [
    [0, 2],
    [1, 1]
  ]
}

Note: the 2 data sets contain the same values but are not the same object.

I inject one of them in a Chartist which draws this chart:
capture_2017-11-24_17 16 41
Then I hide the blue line by unchecking the box:
capture_2017-11-24_17 16 51
Then I dynamically inject the other set by clicking the "Switch data set" button:
capture_2017-11-24_17 17 03
The blue line shows again.

@tarekis
Copy link
Contributor

tarekis commented Nov 24, 2017

I'm afraid I can't follow, what is the expected result? I'm not sure what exactly you are doing and am not sure if this is intended or not, since i assume you are switching references or something.. Please elaborate and include your code so i can investigate.

@pdonias
Copy link
Author

pdonias commented Nov 27, 2017

Hi! I'll try to be clearer.
The expected result was for the blue line to stay hidden when switching data set. As you can see on the last screenshot, the blue checkbox is unchecked while the blue line is showing. I don't think this should happen.

Here's my code for the 2 line example:

Code
import React, { Component } from 'react'
import ChartistGraph from 'react-chartist'
import ChartistLegend from 'chartist-plugin-legend'

const DATA1 = {
  series: [
    [0, 2],
    [1, 1]
  ]
}

const DATA2 = {
  series: [
    [0, 2],
    [1, 1]
  ]
}

export default class extends Component {
  state = {
    data: DATA1
  }

  _switch = () => this.setState({
    data: this.state.data === DATA1
      ? DATA2
      : DATA1
  })

  render () {
    const opts = {
      showArea: true,
      height: 300,
      plugins: [
        ChartistLegend()
      ]
    }

    return <div>
      <button onClick={this._switch}>Switch data set</button>
      <div>
        <ChartistGraph
          type='Line'
          data={this.state.data}
          options={opts}
        />
      </div>
    </div>
  }
}

And here's a more concrete example to help you understand what my issue is:

I'm injecting some network stats into a chartist graph:

capture_2017-11-27_09 23 22

The stats are updated every 10 seconds by injecting a new data set.
When I uncheck a checkbox, the corresponding line disappears, which is fine:

capture_2017-11-27_09 23 32

But a few seconds later, on the next data update, the line shows up again:

capture_2017-11-27_09 23 45

The expected result would be for the red line to stay hidden until I check the box again.
Like in the 2 line example, on each update, a new object is injected (new reference), I am not updating the previous object.

I hope I've made myself clear :)

@tarekis
Copy link
Contributor

tarekis commented Nov 27, 2017

All clear now, I agree with you, that should not happen.
Without rigorously checking the code, I assume the issue is the object references the legends uses to determine display gets lost as you use a new object. I'll investigate if this should be implemented different (or can be), or the library should check this, regarding the hopefully soon-to-come change in which it should support dynamic changes with e.g. React, as you're using it.

You might have already seen by the amount of open issues, I'm very, very busy with things besides maintaining this project, so my throughput is really low right now. I'll try to find some time soon.

@msj121
Copy link

msj121 commented Oct 8, 2019

What happens after looking at the code is quite straightforward. Legend is called at initialization of plugin. Clicking a series element will remove it from the chart data entirely. So updating the chart data will override whatever the plugin has done until now.

Worse, after clicking on the legend you will get old data instead of new data because at initialization it took the data.

Even worse, there is no way to access the plugin variables to manually update them. The plugin should get called on data updates or something. In reality Chartist should allow you to change data and have properties for data like "visible:false" to avoid this entire mess.

Currently (horrible workaround), I check legend elements if they are hidden, recreate chart from scratch and "click" the legend items through javascript, there is a flicker of course.

let lastChart; //global variable?
...
       let hiddens = [];
        if(lastChart){
          document.querySelectorAll(".ct-legend .inactive").forEach((item)=>{
            hiddens.push(item.getAttribute("data-legend"));
          });
        }
        lastChart = new Chartist.Line('#ct-chart', {
          labels: timestamps,
          series:series
        }, {
         
          plugins: [
              Chartist.plugins.legend({
                  className: 'crazyPink',
                  
              })
          ]
        });
        setTimeout(()=>{
          if(hiddens.length){
            hiddens.forEach(index=>{
              let item = document.querySelector(".ct-legend [data-legend='"+index+"']");
              if(item)
                item.click();
            });
          }
        },100);

@flefloch-payps
Copy link

Hello,
are there any news on this problem (other than the workaround provided by @msj121 ) ?
It seems this project is quite abandoned (no updates since a while).
Is someone aware of a fork which could be used instead of this project?

@Martin12350
Copy link

If somebody still got issue like me, when you cannot have legend while updating data, here is my solution. 4 years later woow.

In CSS add class:
.ct-hidden { visibility: hidden; }

In JS remove all references to originalSeries and seriesCopy (line 97, 183, 192, 202).
No needed. Definitely could be cleaned much more, but did not want to dig too deep.

Edited/added lines 155, 161, 171, 175.

if (removedSeriesIndex > -1) {
   // Add to series again.
   chart.data.series[seriesIndex].className = chart.data.series[seriesIndex].className.replace('ct-hidden','');    //<--remove class
   removedSeries.splice(removedSeriesIndex, 1);
   li.classList.remove('inactive');
} else {
   if (!options.removeAll) {
      // Remove from series, only if a minimum of one series is still visible.
      if ( chart.data.series.length > removedSeries.length+1) {       //<--if not last
         chart.data.series[seriesIndex].className += ' ct-hidden';   //<--add class
         removedSeries.push(seriesIndex);
         li.classList.add('inactive');
      }
      // Set all series as active.
      else {
         removedSeries = [];
         var seriesItems = Array.prototype.slice.call(legendElement.childNodes);
         seriesItems.forEach(function (item) {
            item.classList.remove('inactive');
         });
         chart.data.series.forEach(function (item) {
            item.className = item.className.replace('ct-hidden','');   //<--remove class from all items 
         });
      }
   }
   else {
     // Remove series unaffected if it is the last or not
     chart.data.series[seriesIndex].className += ' ct-hidden';    //<--add class
     removedSeries.push(seriesIndex);
     li.classList.add('inactive');
   }
}

It has one dis/advantage - depending how you watch on it.
The graph will not adjust axis when series is hidden.
But for me, it was actually desired, so will have same still ratio while switching series.

Anyway now you can update data and chart:

data.series[0].data = Array(10).fill().map(() => ({x: Math.round(Math.random() * 10), y: Math.round(Math.random() * 50) }));
chart.update();

Maybe somebody will use just idea and make the code looks better :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants