Angular2 - ngFor directive does not display deleted item

I have an Item and Item container where the children will be added and removed from its container. Adding is fine, and deleting does nothing. The angular2 * ngFor directive does not seem to work when any of the children are removed.

    import { NgFor} from 'angular2/common';
    import { bootstrap } from 'angular2/platform/browser';
    import { Component, View, Directive, OnDestroy, Input, enableProdMode } from 'angular2/core';
    import { CORE_DIRECTIVES} from 'angular2/common';


    @Component({selector: 'itemcontainer',})
    @View({ template: `<ul (click)="$event.preventDefault()">
                       <li *ngFor="#it of items">Any Item</li>
                       </ul>
                       <div><ng-content></ng-content></div>`,

            directives: [NgFor],
    })
    export class ItemContainer {
        public items: Array<Item> = [];

        public addItem(item: Item) {
            this.items.push(item);
        }

        public removeItem(item: Item) {
            var index = this.items.indexOf(item);
            if (index === -1) {
                return;
            }

            console.log(`Index about to remove: ${index} this.items length: ${this.items.length}`);
            this.items.slice(index, 1);
            console.log(`this.items length: ${this.items.length}`);
        }
    }

    @Directive({ selector: 'item' })
    export class Item implements OnDestroy {

        @Input() public heading: string;

        constructor(public itemcontainer: ItemContainer) {
            this.itemcontainer.addItem(this);
        }

        ngOnDestroy() {
            this.itemcontainer.removeItem(this);
        }
    }

    @Component({
        selector: 'my-app'
    })
    @View({
        template: `<div (click)="$event.preventDefault()">
            <button type="button" (click)="addItem()">Add item</button>
            <button type="button" (click)="removeItem()">Remove item</button>

        <itemcontainer>
            <item *ngFor="#containerItem of containerItems" [heading]="containerItem.title">Content </item>
        </itemcontainer>
    </div>`,

        directives: [CORE_DIRECTIVES, Item, ItemContainer],

    })

    class Tester {

        private counter: number = 2;

        public containerItems: Array<any> = [
            { title: 'Item1' },
            { title: 'Item2' },
        ];

        addItem() {
            this.containerItems.push({ title: `Item ${this.counter}` });
        }

        removeItem() {

            if (this.containerItems.length > 0) {
                this.containerItems.splice(this.containerItems.length - 1, 1);
            }
        }
    }

    enableProdMode();
    bootstrap(Tester);

Here's what the DOM looks like after adding and removing two new elements:

    <itemcontainer>
        <ul>
            <li>Any Item</li>
            <li>Any Item</li>
            <li>Any Item</li>
            <li>Any Item</li>
        </ul>
        <div>
            <item>Content </item>
            <item>Content </item>
        </div>
    </itemcontainer>

The problem is that the li part is not deleted. Any idea?

(I tested it with angular 2.0.0-beta.3 and 2.)

+4
source share
5 answers

In fact, Angular2 only detects changes when an instance changes. I mean, the array instance does not change inside the elements.

(. slice):

public removeItem(item: Item) {
  var index = this.items.indexOf(item);
  if (index === -1) {
    return;
  }

  console.log(`Index about to remove: ${index} this.items length: ${this.items.length}`);
  this.items.slice(index, 1);
  console.log(`this.items length: ${this.items.length}`);

  this.items = this.items.slice();
}

:

+3

splice() not slice(). Angular .

this.items.splice(index, 1);

NgFor , , - .

Plunker

, :

import { NgFor} from 'angular2/common';
import { CORE_DIRECTIVES} from 'angular2/common';

     directives: [NgFor],

, .

<li *ngFor="#it of items">Any Item {{it | json}}</li>

:

: TypeError: JSON [ {{it | json}} ItemContainer

+12

, . , :

    this.items = [
        ...this.items.slice(0, index),
        ...this.items.slice(index + 1, this.items.length)
    ];
+1

, , (.. ). , :

export class SharedService {
    public items: Array<Item>=[];

    public addItem(item:Item) {
      this.items.push(item);
    }

    public removeItem(item:Item) {
       var index = this.items.indexOf(item);
      if (index >=0) {
        this.items.splice(index,1);
      }
    }
}

/ Item:

@Directive({ selector: 'item' })
export class Item implements OnDestroy {

    @Input() public heading: string;

    constructor(public sharedService:SharedService) {
        this.sharedService.addItem(this);
    }

    ngOnDestroy() {

        this.sharedService.removeItem(this);

    }
}

ItemContainer:

@Component({selector: 'itemcontainer',})
@View({ template: `<ul (click)="$event.preventDefault()">
                   <li *ngFor="#it of items">Any Item </li>
                   </ul>

                   <div><ng-content></ng-content></div> `,

        directives: [NgFor],
})
export class ItemContainer {
    public items: Array<Item> = [];
    constructor(public sharedService:SharedService) {
       this.items = this.sharedService.items;
    }


}

Plnkr

0

, splice detecChange @McLac ,

this.items = [
    ...this.items.slice(0, index),
    ...this.items.slice(index + 1, this.items.length)
];

. . :

let idx = this.prds.indexOf(prd);
if(idx==-1){
  return
};
/*    it was like this before, consol.log show deleted array correctly just the UI has no change..
for(let i =0; i< this.prds.length; i++){
  if(this.prds[i]==prd){
    this.prds.splice(i,1);
    break;
  }
}
*/
this.prds = [
  ...this.prds.slice(0,idx),
  ...this.prds.slice(idx+1,this.prds.length)
];
-1

Source: https://habr.com/ru/post/1628500/


All Articles