3
votes

I am using ngFor to iterate over a simple array to output list items.

At some point, I want to re-create the array contents and update the ngFor content. Pushing data to the array seems to work as intended (i.e. the item is added onto the end of the list in the component template) but when I recreate the array from scratch, it seems the old data isn't removed?

tests =  [{output: '1'}, {output: '2'}];
clear(){
    this.tests = [{output: '3'},{output: '4'}];
    // this.tests.push({output:'b'});
}

Template

<button (click)="clear()">Clear</button>
<ul>
   <li *ngFor="let test of tests">{{test.output}}</li>
</ul>

Expected output should be a list of 1,2 and on button click, recreate the list as 3,4. What I get instead is: 3,4,1,2 (the old data persisting at the end and not removed from DOM?) Using a push results correctly in 1,2,b (with b appended at the end).

What am I doing wrong? How can I effectively recreate the contents of the array and ask ngFor to delete the old DOM and reiterate over the contents correctly?

I've tried using triggering event changes manually (e.g. changeDetectorRef and NgZone and even top-level application-ref) but none of them work as desired.

3
your code works to meEliseo
Odd, I've just setup a Plunkr to test it and it indeed does work as expected. But on my local application I can't seem to get it to work. Any ideas why this might be? See gif below. gyazo.com/fbfa505ae7bab0bd117c49e8c7c14588NJ.
Doh! After troubleshooting this for over 2 hours, the issue was caused by some unrelated error in console from another module. Guess it interfered with modifying the DOM in some way. Thanks for help all.NJ.
@NJ. You saved my life.gfels

3 Answers

1
votes

Try this does it might work

tests =  [{output: '1'}, {output: '2'}];
clear(){
    this.tests = [];
    this.tests = [{output: '3'},{output: '4'}];
    // this.tests.push({output:'b'});
}
1
votes

I would suggest not replacing the value of tests variable, but first making it empty by setting tests.length = 0 and then adding the values via push:

tests =  [{output: '1'}, {output: '2'}];

clear() {
    this.tests.length = 0;
    this.tests.push(...[{output: '3'}, {output: '4'}]);
}
0
votes

Check out this plunker, it does what expected

https://plnkr.co/edit/WzPdaD1AYfmJxLhhYZnk?p=preview

//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <button (click)="clear()">Clear</button>
<ul>
   <li *ngFor="let test of tests">{{test.output}}</li>
</ul>
    </div>
  `,
})
export class App {
  name:string;
  tests =  [{output: '1'}, {output: '2'}];
  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }
  clear(): void {
    this.tests =  [{output: '3'}, {output: '4'}];
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}