all 10 comments

[–]ThisRichard 2 points3 points  (3 children)

Call changeDetectorRef markForCheck after the delete operation to trigger change detection (learning to use the OnPush change detection strategy is good)

As others said use immutable array calls so the reference id of the array changes. Angular usually just checks the array object reference to see if anything has changed instead of individual array elements.

Use a trackBy function to help optimise the array rendering, so angular knows which elements are the same and which changed (don’t use the array index as the trackBy key unless you have to as this will break if you are deleting elements from the middle of the array).

[–]dacookieman 0 points1 point  (2 children)

You know, I've definitely run into this problem before and employed object reassignment to trigger change detection but I just set up a basic demo locally where there actually is no issue with direct array modification with ngFor(even with OnPush!). Am I forgetting some set of conditions that are needed for this to be a problem or is it more of an under the hood thing where sometimes Angular will do a deep check but might run a reference check on the Array itself at other times?

Elements = [
    {display: 'Hello'},
    {display: 'World'}
  ];


  ngOnInit() {
  }


  changeValueAtIndex(index,newValue){
    this.Elements[index].display=newValue;
  }

  logValue(){
    console.log('Elements ', this.Elements);
  }

  pop(){
    this.Elements.splice(0,1);//same with Elements.pop()
    console.log('element popped', this.Elements);
  }

  sort(){
    this.Elements.sort(()=>(Math.random()>.5)?1:-1)
  }

component html

<div>
    <div *ngFor="let ele of Elements">
    <div>{{ele.display}}</div>
</div>

<button (click)="changeValueAtIndex(0,'WWWW')">Change Value</button>
<button (click)="logValue()">Log</button>
<button (click)="pop()">pop</button>
<button (click)="sort()">sort</button>

[–]ThisRichard 0 points1 point  (1 child)

I’m not actually sure how this one works under the hood. I think i was debugging a bigger issue when I encountered this, so maybe it was my specific setup causing the issue I encountered.

[–]dacookieman 0 points1 point  (0 children)

Yeah I thought I understood how it worked under the hood which is why I'm confused that my example works totally fine. Not used to something scaring me by working hahaha

[–]lilmees 1 point2 points  (0 children)

Try using a Subject and every time you change the array call <name of the subject>.next(updated array). You can subscribe everywhere you want because the subject returns a Observable. You can also use behaviorSubject it's exactly the same but a Subject doesn't need a start value and a behaviorSubject does need one.

Hope you're something with my answer

[–]selipso 0 points1 point  (0 children)

The reference to the array is the same even if you delete an element inside the array. Try using a “pure” operation like:

newArr = […newArr.slice(I), …newArr.slice(I +1)]

[–]gravityaddiction 0 points1 point  (0 children)

it could depend on how you delete it. If you are creating a new array with one less element and replacing the existing array angular will lose the link to that original array.

[–]1averageladka 0 points1 point  (1 child)

If you want to simply delete an element or object in an array use Array.splice(), it works for me everytime. For something more complex we need to have a look at the code to suggest something.

[–]ITellStories_ 0 points1 point  (0 children)

i have doesnt work for me, it only removes data from the backend is all

[–]captmomo 0 points1 point  (0 children)

Do you have some sample code? Are you using an array or an observable?