1

I have an angular component that fetch some data from the backend and iterates it into another component using *ngFor . For testing purposes I have written a randomize() function which creates random data and returns it instead of hitting the backend api (api not ready yet) . But what I have observed is that even though the data changes the onChange was not getting triggered. Could someone please explain what is happening as I am new to angular.

mainComponent.ts

let mockData = {
  "someField": "some value",
  "someField": ["..."],
  "data": [
    {
      "someField": "POL",
      "data": [
        {
          "someField": 0,
          "someFieldThatIsChanged": [7.544, 2.345, 7, 8.452, 2, 6],
          "someField": [100.0, 0, 100.0, 0, 0],
          "someField": [15470, 345, 546, 2345],
          "someField": [15467, 345, 456, 654, 23456],
          "someField": [2312, 32542, 45623, 543, 45646],
          "someField": ["some value", "some value", "some value", "some value", "some value"]
        },
        {
          "someField": 0,
          "someFieldThatIsChanged": [7.544, 2.345, 7, 8.452, 2, 6],
          "someField": [100.0, 0, 100.0, 0, 0],
          "someField": [15470, 345, 546, 2345],
          "someField": [15467, 345, 456, 654, 23456],
          "someField": [2312, 32542, 45623, 543, 45646],
          "someField": ["some value", "some value", "some value", "some value", "some value"]
        },
        {
          "someField": 0,
          "someFieldThatIsChanged": [7.544, 2.345, 7, 8.452, 2, 6],
          "someField": [100.0, 0, 100.0, 0, 0],
          "someField": [15470, 345, 546, 2345],
          "someField": [15467, 345, 456, 654, 23456],
          "someField": [2312, 32542, 45623, 543, 45646],
          "someField": ["some value", "some value", "some value", "some value", "some value"]
        },]
    }]
}

public randomize(randomData) {
  randomData.forEach(element => {
    element.type = element.type + "type";
    element.data.forEach(dataElement => {

        const random = [
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100)];
        dataElement.someFieldThatIsChanged = random;
      }
    )
  });
  return randomData;
}

getGraphData(): void {
  let fetchedData;
  let body = this.createGraphApiRequest(this.mockData);
  this.modelData = body.data;
}

I have this mockData that is exported from one ts to provide the mockData initially which i use to load the ui initially when the browser render the page. Again upon ui event I am taking this same mock data and then modifying values within the structure randomly to produce some random data.

mainComponent.html

<div *ngFor='let model of modelData' class="chart-overflow">
  <app-subComponent [data]='model' [labels]='labelValues'></app-subComponent>
</div>
Philipp Meissner
  • 5,273
  • 5
  • 34
  • 59
Ananthapadmanabhan
  • 5,706
  • 6
  • 22
  • 39
  • https://stackoverflow.com/questions/34796901/angular2-change-detection-ngonchanges-not-firing-for-nested-object Hope this helps! – Jins Thomas Shaji Jan 27 '20 at 09:11
  • 3
    you should not use `forEach` but use `map` to make sure you get a new array reference saved to your `modelData`. Or you can do `element.data = [ ...element.data]`, just to test if that's the issue. You probably have to do the same thing for the nested objects as well – Poul Kruijt Jan 27 '20 at 09:12
  • @PierreDuc I think you have it right, since it worked for me when i tried hitting a temporary mock endpoint that i created which just returned a json. So , creating new reference should work from code as well .If you could provide it as an answer I will accept it. – Ananthapadmanabhan Jan 27 '20 at 09:25

1 Answers1

2

Try to use map functuon as it is create new array. So change detection will detect new reference and will update UI:

public randomize(randomData) {
  randomData.forEach(element => {
    element.type = element.type + "type";
    element.data.map(dataElement => ({

        const random = [
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100),
          Math.round(Math.random() * 100)];
        return dataElement.someFieldThatIsChanged = random;
      })
    )
  });
  return randomData;
}
StepUp
  • 36,391
  • 15
  • 88
  • 148
  • Apparently after some documentation reading i understand that change detection will only occur if we either change the array reference or add or remove values from the array. So , your suggestion should work . But I think since i have nested arrays, I will have to update those references as well like @PierreDuc suggested. – Ananthapadmanabhan Jan 27 '20 at 09:23