Search code examples
angulartypescriptd3.jsangular-changedetectionngonchanges

Angular - how do I get data to load with ngOnChanges


I have a demo here

It's a angular app where I'm trying to create a D3 chart.

The chart data is created with a createDate function, creating random data and dates.

I want the chart to update with the update button so I'm using ngOnChanges but this doesn't create the chart when the pages load.

The ngOnInit commented out loads the chart on page load.

ngOnChanges(changes: SimpleChanges) {
    if(!changes.data) return;

    if(this.hasPreviousData){

      this.createData()

      this.stack = d3.stack()
          .keys(['data_1', 'data_2', 'data_3', 'data_4'])

      this.createStack(this.testData);
    }else{

      this.createData()

      this.stack = d3.stack()
        .keys(['data_1', 'data_2', 'data_3', 'data_4'])

      this.initScales();
      this.initSvg();
      this.drawAxis();
      this.createStack(this.testData);

      this.hasPreviousData = true;
    }
  }

Solution

  • The reason ngOnChanges is not working because it works on @Input param changes. In your case, you are simply changing the value of the component from the component itself.

    Take a look at this demo. I have made some code changes in your demo code and it seems to be doing the same thing which you are expecting.

    You can put the graph creation logic in the createData() itself and rest is handled:

      createData() {
        this.testData = [];
        this.years = Math.floor(Math.random() * this.dates.length)
        console.log(this.years)
        for(let i:number= 0; i<=this.years; i++){
          this.testData[i] = {
            data_1: Math.floor(Math.random() * (this.max - this.min)),
            data_2: Math.floor(Math.random() * (this.max - this.min)),
            data_3: Math.floor(Math.random() * (this.max - this.min)),
            data_4: Math.floor(Math.random() * (this.max - this.min)),
            date: this.dates[i]
          }
        }    
        this.stack = d3.stack()
          .keys(['data_1', 'data_2', 'data_3', 'data_4']);
        if(this.hasPreviousData){
          this.createStack(this.testData);
        }else{
          this.hasPreviousData = true;
          this.initScales();
          this.initSvg();
          this.drawAxis();
          this.createStack(this.testData);
        }
      }