1

I need help please, I've been trying for couples of days to create a grid with objects that I then insert into an array. Each row in the grid represents the object with a select dropdown and list of colomns with input box. My problem is that when I change a value of headItem that represents my input box, the value is saved to all the objects in the array via (onRowClick()). I was wondering if I can set ngModel on a row to update only values of that row.

NB: the DOM objects are showing correctly because I index the headItem value headItem.value[childIndex]

<tr *ngFor='#row of listRows; #parentIndex = index'>
        <td>
            <select
                [(ngModel)]="color[parentIndex]"
                (ngModelChange)="sendColorEvent($event, row)"
                class="form-control">
                <option *ngFor='#obj of row.availableColors'>{{obj}}</option>
            </select>
        </td>
        <td *ngFor='#headItem of row.headList; #childIndex = index'>
          <input [(ngModel)]="headItem.value[childIndex]" (ngModelChange)="onRowClick($event, row, headItem)" type="number">
        <td>
          <input readonly="readonly" [(ngModel)]="totalAmount" type="number">
        </td>
    </tr>

In the console log you can see that in array all the row have the same value, the last typed.

  onRowClick(quantity, row, headItem) {
  headItem.value = quantity;
  console.log(this.listRows)
  this.getTotal();
 }

enter image description here

PLunker grid

kyserslick
  • 591
  • 1
  • 10
  • 27

1 Answers1

1

The issue you are facing is that in your code, when you are creating both instances of your object:

const gblRowVal1 = 
     new GridRowValues(1, this.color, this.headList, this.availableColors)

const gblRowVal2 = 
     new GridRowValues(2, this.color, this.headList, this.availableColors)

you are setting the the same array headList (and availableColors which you are using differently so it doesn't matter that array is same).

Using the same array means that the array is then of course same for both objects. So whatever you do to one array, will then happen to the other.

What you need to do is a deep clone of that array. A shallow copy won't work, because it still keeps the object references and we need to get rid of that too. There are some possible solutions for deep cloning, for using for example lodash library. But with we can also do it by mapping the existing array to new array and using Object.assign like so:

const gblRowVal1 = new GridRowValues(1, this.color, 
   this.headList.map(x => Object.assign(new RefQuantities(), x )),
   this.availableColors)

const gblRowVal2 = new GridRowValues(2, this.color, 
   this.headList.map(x => Object.assign(new RefQuantities(), x )), 
   this.availableColors)

Here are also other solutions if you want to check them out: How do you clone an Array of Objects in Javascript? I personally like the above approach I showed you, especially since you want to to cast the data to your class RefQuantities.

Now these arrays are different arrays and changes in either will not affect the other.

Here's your plunker: https://plnkr.co/edit/HozFyjGvwL6mgmclliiW?p=preview

AT82
  • 71,416
  • 24
  • 140
  • 167
  • PS... is there a reason for using beta version of Angular?? I would suggest you'd update it to at least Angular 2 final at the minimum, since beta versions are... well **beta** versions :D But that's just a suggestion and if you have the possibility to upgrade it :) – AT82 Jul 22 '17 at 22:28
  • It's just a test plunker, indeed I'm using a final version – kyserslick Jul 23 '17 at 10:13
  • Works great, tkx a lot @AJT_82 – kyserslick Jul 23 '17 at 10:13
  • Glad to hear it worked! :) Have a good end of the weekend and happy coding! – AT82 Jul 23 '17 at 10:22