2016-02-12 81 views
4

我有一个项目容器和项目模式,应该在其容器中添加和删除子项目。添加是好的,而删除什么都不做。看起来,当删除任何子项时,angular2 * ngFor指令不起作用。Angular2 - ngFor指令不会映射删除的项目

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); 

这里是DOM照顾两个新项目添加和删除,如:

<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> 

的问题是,李部分不删除。任何想法?

(I具有角2.0.0-beta.3和2测试它)

回答

3

事实上,Angular2仅检测变化的时候,例如改变。我的意思是数组的实例在元素内部没有改变。

你可以使用这个(见第二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

由于'正在使用ngFor',角度变化检测会注意到,当项目被添加或删除就好了。这里没有更改检测的问题。这个问题很容易用'splice()'而不是'slice()'来解决。详情请参阅我的回答。 –

+0

这很奇怪!我几乎肯定会遇到同样的问题,因为我修正了这个问题......在您发表评论之后,我做了一个新的尝试(请参阅此PLUNK:https://plnkr.co/edit/YZkC74yOnJgSLEdzjcOE?p =预览),但我不能重现它...感谢您指出这一点,马克! –

+0

也许你正在考虑无状态管道与数组一起使用的情况 - 例如http://stackoverflow.com/a/34497504/215945 解决该问题的一种方法就是完成您在此处所做的工作。 。改变数组引用。 –

1

是的,确实是变化检测。这是什么工作对我来说:

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

的问题可能有不正确的设置正向引用(即你不应该宣布其之前使用的类)。为了解决这个问题,你可以使用一个共享服务:

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; 
    } 


} 

Demo Plnkr

+2

我不认为这里有任何前瞻性的参考问题。我认为问题只是使用'slice()'而不是'splice()'。如果感兴趣,请查看我的答案 –

+0

哎呀...我完全错过了。谢谢 – pixelbits

12

您需要使用splice()而不是slice()。这里没有关于角度变化检测的问题。

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> 

,并记下错误:

EXCEPTION: TypeError: Converting circular structure to JSON in [Any Item {{it | json}} in ItemContainer

+0

随着Angular 2.4.0,这是正确的答案。我正在从AngularJS迁移ng-repeat代码,并且在这里围绕ngFor对于变化检测而言,被各种无效信息所迷惑。您只需编辑现有项目,通过push()添加新项目或通过splice()删除项目,然后它将显示在视图中。 – bob

-1

我有你同样的问题,即使我用接头或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) 
];