2016-11-27 27 views
0

私はAngular2について学んでいます& RxJS observables。私はシミュレートされたhttp.getとの結果を表示するシンプルなフォームを作成しました。は新しいアイテムを作成することができます。ngの内部での行動について<form>

新しいアイテムをngForで参照される配列の最上部に追加し、表示されたアイテムのリストの先頭に拡張機能を追加したいので、これを達成するためにpush()とは対照的にunshift()を使用しました。しかし、私がこのアプローチを使用するとき、私はいくつかの望ましくない動作を見ます。新しい項目が配列に追加されると、既存の出力の最初の項目が変更されます。

私が言ったように、私はちょうど学んでいるので、私は何かを見逃してしまった場合、plsは忍耐強いですが、誰かが私がここで何が起こっているのか理解するのを助けることができますか?私は私の問題を説明するためにこの塊を作りました。どんな洞察力も大変高く評価されます。

import { Component, OnInit } from '@angular/core'; 

@Component({ 
selector: 'demo', 
template: ` 
    <button (click)="createItem()">Create</button> 
    <button (click)="getItems()">Reset</button> 

<form> 
    <div class="form-group" *ngFor="let item of items; let i=index" > 
     <div style="padding-top: 50px;"> 
      <div class="col-xs-4"> 
       <label id="itemIdLabel-{{i}}" for="itemIdDiv-{{i}}">Id</label> 
       <div id="itemIdDiv-{{i}}">{{item.id}}</div>               
      </div> 

      <div class="col-xs-8"> 
       <label id="itemNmLabel-{{i}}" for="itemNmInput-{{i}}">Name</label> 
       <input id="itemNmInput-{{i}}" name="itemNmInput-{{i}}" [(ngModel)]="item.nm" type="text" class="form-control"> 
      </div> 

      <div class="row" style="padding-top: 10px;"> 
       <div class="col-xs-12"> 
        <button (click)="deleteItem(item.id, i)">Delete</button> 
       </div> 
      </div> 

     </div> 
    </div> 
</form> 
`, 
}) 

export class DemoComponent implements OnInit{ 
items = new Array<Item>(); 

constructor() {} 

ngOnInit(){ 
    this.getItems(); 
} 

getItems(){ 
    this.initItems(); 
} 

createItem(){ 
    //create a new item without an id. this will be committed once required fields are filled 

    //this works fine 
    //this.items.push(new Item("new", "newItem")); 

    //this does not 
    this.items.unshift(new Item("new", "newItem")); 
} 

deleteItem(id, index){ 
    this.items.splice(index,1); 
} 

    initItems(){ 
    //simulating data coming back from a web service call with ids intact 
    this.items.length = 0; 
    this.items.push(new Item("first", "firstItem")); 
    this.items[0].id = '001'; 

    this.items.push(new Item("second", "secondItem")); 
    this.items[1].id = '002'; 

    this.items.push(new Item("third", "thirdItem")); 
    this.items[2].id = '003'; 

    } 
} 

export class Item { 
public id: string; 

constructor(public nm: string, 
public dsc: string){} 
} 
+0

*質問に[MCVE] *入れてください。 – jonrsharpe

+0

あなたの要求に応じて – rswillis

+0

** M **と** C ** **は 'Item'の詳細、' ItemService'、完全なHTMLマークアップはすべて関連していますか?どちらかを切り取ったり、それらを組み込んでください。 – jonrsharpe

答えて

0

https://embed.plnkr.co/FGi1ot/

は[OK]を、よりngForの研究と、閉じたバグを見た後、私は一緒に欠けている部分を置くことができました。他の人がこの問題を回避するのに役立つことを期待して回答を投稿しています。それはngFor APIで文書化されているので、バグとして分類されているとは思われません。

https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html

問題は、変更の追跡に関係しています。 ngForは、DOM要素を正常に再描画するために明示的なIDを必要とするようです。しかし、私は実際には<form>の外でこの動作に気づいていないので、そこにいくつかの相互作用がなければなりません。

とにかく... Angular2は素晴らしいです。続ける。もっと表示するものがありません:)

は、ここに1つとして機能するが、私は私の例で変更

https://plnkr.co/edit/g8fDquNgUY9MYoget8O4

要素以下のようですが期待更新plunkです。

<div class="form-group" *ngFor="let item of items; let i=index; trackBy:itemIdentity"> 

...

itemIdentity(index, item) { 
console.log("index:{i}, item:{s}", index, item) 
return index; 
} 
+0

奇妙なことに、DOMの要素を再描画するためのブール値の変更を追跡するための別の答えを読んで、この質問を考えました。あなたが一緒に作品を配置し、解決策を見つけることができたことを喜んで。配列自体が変化している(全く新しいオブジェクト!)ので、予期しない動作のように思えます。 – silentsod

関連する問題