11

I have two child components. They are sharing data from a json file that I am loading using the http.get/subscribe method. For some reason, when I push data into the array, it doesnt update in the view. It shows the updated array in the console though.

app component loading the data from a service

this.dataService.getData()
 .subscribe(
     data => {
       this.data = data;
     },
     (err) => console.log('Error: ', err),
     () => console.log("success!")
   );

I am using inputs to access the data in my child component. Are there any ways in Angular 2 to update the view when new values are pushed into the array.

Display Component

<div *ngFor="let i of items; let k = index"><h1>{{i.title}}</h1> <p>{{i.desc}}</p></div>

The Button Component

<button (click)="addItem(i)">Add Item</button>

The Component Function
addItem(i){
  let data = {title: "Some title", desc: "Some desc"};
  this.data.list[i].items.push(data);
}
LadyT
  • 649
  • 2
  • 12
  • 31
  • What is `dataService`? – Günter Zöchbauer Jan 23 '17 at 18:49
  • @GünterZöchbauer It's an angular service – LadyT Jan 23 '17 at 18:50
  • 1
    Can you show us the component code? What you posted looks correct; the problem might be elsewhere. – chrispy Jan 23 '17 at 18:55
  • More details please :D what API does it call to get the data? – Günter Zöchbauer Jan 23 '17 at 18:55
  • @GünterZöchbauer the dataService does this `getData() { return this.http.get('data.json') .map((res:Response) => res.json()); }`. Then I call it in my app component. I use the @Input() to access the data in the child component. I have a button that runs a function that pushes data into an array. – LadyT Jan 23 '17 at 18:57
  • @chrispy The component code for the button goes like this `addItem(i){ let data={name: "some name", desc: "some desc"}; this.data.tasks[i].items.push(data); } ` – LadyT Jan 23 '17 at 19:00
  • 1
    are you using the OnChanges lifecycle hook? You might need to call that if you're doing some more work on the update to "data" :) – chrispy Jan 23 '17 at 19:09
  • @chrispy I tried OnChanges on the display component, and it didnt work. I have two components. The button component and the display component which will display the update array elements. They are sibling components. I notice the html update, but the data is blank. – LadyT Jan 23 '17 at 19:12
  • I would just log every step of the process and find out where the data isn't set properly. Unless I see more code, I'm not certain what's wrong. – chrispy Jan 23 '17 at 19:15
  • @chrispy I noticed that it does load the updated array after I click another button. Its very weird. – LadyT Jan 23 '17 at 19:18
  • 1
    @SteveG. I added the code that I am using. A display component to display the data, and a button to push data into the array. – LadyT Jan 23 '17 at 20:19
  • 2
    `ngFor` iterates over `items` not `data` – Günter Zöchbauer Jan 23 '17 at 20:49
  • The code/question is still a bit confusing... How about you fork this plunker to explain a little more? https://plnkr.co/edit/o2YWJVvYiGxP1NmAMRRN?p=preview – Steve Jan 23 '17 at 21:34
  • @SteveG. Yes, this is exactly what I am trying to do! – LadyT Jan 23 '17 at 22:17
  • @SteveG.The i was an index in my parent array. I guess my issue is for some reason, my view wont update unless I click one of the buttons I have in my navigation. – LadyT Jan 23 '17 at 22:28
  • @SteveG. I did fix my problem. Now, everything works great! Thanks for your help on this! – LadyT Jan 23 '17 at 23:03
  • 4
    Possible duplicate of [Why angular 2 ngOnChanges not responding to input array push](https://stackoverflow.com/questions/43223582/why-angular-2-ngonchanges-not-responding-to-input-array-push) – crh225 Mar 15 '18 at 15:20

1 Answers1

11

I have the same problem and I solved this by using spread operator to create a new array of the object rather than to push new element into an existing array.

in your case I would do something like:

addItem(i){
  let data = {title: "Some title", desc: "Some desc"};
  this.data.list[i].items = [...this.data.list[i].items, data];
}
David Sajdl
  • 164
  • 1
  • 10