5

I have a list of objects which I am displaying using a *ngFor on the HTML page. Now the user interacts with UI and changes one of the primitive values(boolean, from false to true).

As per my understanding the *ngFor will only render the changes if the list object is modified completely i.e. removed and added again to the list. If I am right on this concept, then can you please suggest a method to reflect the change in the primitive type without re-initializing the component or modifying the object reference.

For Example:

  <div *ngFor="let item of list">
        <md-checkbox [(ngModel)]="item.selected"></md-checkbox>
  </div>

User clicks on the checkbox, but the checkbox has to be ticked after certain validations from server. So let's say the checkbox needs to be unchecked and user gets a message on snack bar. So I loop through the list and modify item.selected to false. But, the change is not reflected as i modified the primitive type selected(boolean) in the object item. So how to render the new value without reloading or initializing the page again.

Please let me know if more input is required.

Rob
  • 14,746
  • 28
  • 47
  • 65
Sumit Agarwal
  • 4,091
  • 8
  • 33
  • 49

1 Answers1

11

If you use primitive values, you need trackBy

  <div *ngFor="let item of list trackBy:trackByIdx">
        <md-checkbox [(ngModel)]="item.selected"></md-checkbox>
  </div>
  trackByIdx(index: number, obj: any): any {
    return index;
  }

See also Angular2 NgFor inside tree model: wrong order when remove and then add elements

update according to the discussion below

Changing a boolean value bound by ngModel when the input value is changed, may cause ngModel not being updated. Adding an artificial change and callign detectChanges can be used to work around.

constructor(private cdRef:ChangeDetectorRef) {}

deactivate(index: number) {
  this.list[index][0] = true;
  this.cdRef.detectChanges();
  this.list[index][0] = false;
  this.cdRef.detectChanges();
  console.log(this.list);
}

Plunker example

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    Oh my... are you kidding me! I've had several cases already where i thought that this could not be fixed. But apparently, angular already thought about this. Thanks gunter :D. Ah yes, it seems to be relatively new. Still great – Poul Kruijt Nov 29 '16 at 10:12
  • these indexes are stored by angular, can we reset this list of indexes from the component? – Sumit Agarwal Nov 29 '16 at 10:53
  • No. What's the purpose? – Günter Zöchbauer Nov 29 '16 at 10:54
  • I have a pagination feature, where user is moving to next page(data fetched using ajax call, instead of changing the url). The current changes made on first page are also reflected on the data of second page on the very same indexes. – Sumit Agarwal Nov 29 '16 at 10:57
  • Seems like you're using the indexes for something else than what is shown in my answer. – Günter Zöchbauer Nov 29 '16 at 10:59
  • As per my understanding, trackBy is being used to segregate the data based on index. But what i wanna achieve is that, reflect the primitive value from the model on the UI, after I have toggled it in the component. – Sumit Agarwal Nov 29 '16 at 11:29
  • Sorry but I have no idea what " reflect the primitive value from the model on the UI, after I have toggled it in the component." means. – Günter Zöchbauer Nov 29 '16 at 12:04
  • `trackBy:trackByIdx()` should be `trackBy:trackByIdx` without `()`. What's the problem with the Plunker? – Günter Zöchbauer Nov 30 '16 at 08:30
  • When i click the checkbox, I have called a change event where i set the checked flag to false. But then also the checkbox is getting checked instead of remaining as unchecked. – Sumit Agarwal Nov 30 '16 at 10:47
  • This is `ngModel` not recognizing that the value changed from `false` to `true` to `false` https://plnkr.co/edit/hmwkhcNPDgUDW3iiCYln?p=info shows a workaround. – Günter Zöchbauer Nov 30 '16 at 10:57
  • what is the change? Seems like the same plunk which i had created! – Sumit Agarwal Nov 30 '16 at 11:33
  • 1
    Sorry. Plunker doesn't seem to work currently. This one https://plnkr.co/edit/hmwkhcNPDgUDW3iiCYln?p=preview should contain the changes but I couldn't run and test it. – Günter Zöchbauer Nov 30 '16 at 11:50
  • Thanks a lot!, it worked. If you can post this answer as well in the response that would be really fruitful for others too i guess! – Sumit Agarwal Nov 30 '16 at 11:59
  • Glad to hear this worked for you. I updated my answer. – Günter Zöchbauer Nov 30 '16 at 12:03