2017-10-19 2 views
0

提供されているオブジェクト配列を使用してhtmlテーブルをレンダリングする角度コンポーネントを作成しようとしています。角度:@Inputの変更を購読するには

@Inputの変更を検出するためにOnChangesを実装しましたが、動作していないようです。

テストの場合、私はsetIntervalを使用してデータを追加していますが、子コンポーネントには反映されません。

export class NgTableComponent implements OnInit, OnChanges { 

    @Input() data: any[]; 

    private columns: string[]; 
    private rows: string[][]; 

    constructor() { 
     this.columns = []; 
     this.rows = []; 
    } 

    ngOnInit() { 
    } 

    ngOnChanges(changes: SimpleChanges) { 
     console.log(changes); 
     if (changes.data) { 
      this.extractRowsAndColumns(this.data); 
     } 
    } 

    extractRowsAndColumns(objArray: any[]): void { 
     const colSet = new Set<string>(); 
     for (let i = 0; i < objArray.length; i++) { 
      const keys = Object.keys(objArray[i]); 
      for (let j = 0; j < keys.length; j++) { 
       colSet.add(keys[j]); 
      } 
     } 
     this.columns = Array.from(colSet); 

     for (let i = 0; i < objArray.length; i++) { 
      const obj = objArray[i]; 
      const row = []; 
      for (let j = 0; j < this.columns.length; j++) { 
       if (obj.hasOwnProperty(this.columns[j])) { 
        row.push(obj[this.columns[j]]); 
       } else { 
        row.push(null); 
       } 
      } 
      this.rows.push(row); 
     } 
    } 
} 

NG-table.component.html:

<div> 
    <table class="ngtable"> 
     <tr> 
      <th *ngFor="let col of columns"> 
       {{col}} 
      </th> 
     </tr> 
     <tr *ngFor="let row of rows"> 
      <td *ngFor="let cell of row">{{cell}}</td> 
     </tr> 
    </table> 
</div> 

これは私がこれまで持っているコード、

NG-table.component.tsをIT

私はapp.componentで上記のコンポーネントを使用しています

app.component.ts: app.component.html

export class AppComponent { 
    timer: any; 
    count = 0; 
    constructor() { 
    const o: any = { 
     'id': 1, 
     'name': 'Jeanette', 
     'last_name': 'Penddreth', 
     'email': '[email protected]', 
     'gender': 'Female', 
     'ip_address': '26.58.193.2' 
    }; 
    this.timer = setInterval(() => { 
     this.data.push(o); 
     console.log(this.data.length); 
     if (this.count++ === 5) { 
     clearInterval(this.timer); 
     } 
    }, 1000 * 1); 
    } 

    data = [{ 
    'id': 1, 
    'name': 'Jeanette', 
    'last_name': 'Penddreth', 
    'email': '[email protected]', 
    'gender': 'Female', 
    'ip_address': '26.58.193.2' 
    }, { 
    'id': 2, 
    'name': 'Giavani', 
    'last_name': 'Frediani', 
    'email': '[email protected]', 
    'gender': 'Male', 
    'ip_address': '229.179.4.212' 
    }, { 
    'id': 3, 
    'name': 'Noell', 
    'last_name': 'Bea', 
    'email': '[email protected]', 
    'gender': 'Female', 
    'ip_address': '180.66.162.255' 
    }, { 
    'id': 4, 
    'name': 'Willard', 
    'last_name': 'Valek', 
    'email': '[email protected]', 
    'gender': 'Male', 
    'ip_address': '67.76.188.26' 
    }]; 
} 

<app-ng-table [data]="data"></app-ng-table> 

がどのようにコンポーネントのアップデート@Inputの変更を行うことができますか?

UPDATE:私はこれを実証plunkr作成した:あなたの問題の簡単な解決策としてhttps://plnkr.co/edit/szz1SNooQ1vIZhnFgiys?p=preview

+0

は* [このを参照することにより、入力の観測可能にしようとしています*回答**](https://stackoverflow.com/questions/44467336/observable-of-input-property/44467942#44467942) – Aravind

+0

助けに興味がある人は、こちらのコード全体をご覧ください:https:// github .com/cyberpirate92/ngTable – cyberpirate92

答えて

1

TimHoviusが述べたように、角度は参照チェックを行うだけです。同じ配列にプッシュしているので、ng-table.componentは変更を検出していません(入力への参照は同じです)。あなたができることの1つは、配列の浅いコピーを作成することです。

addItem(): void { 
    this.data.push(this.data[this.data.length-1]); 
    // create shallow copy of array, since this is a new array (and new reference) ngOnChanges hook of the ng-table.component will fire 
    this.data = this.data.slice(0); 
} 

今NG-table.componentは、入力がここ

を変更し、火災ngOnChangesたことを検出し、これをデモplunkr(https://plnkr.co/edit/2tdMEA9PLc2TEL4Gy4Lp?p=preview

+0

@ cyberpirate92私のplnkrを追加するのを忘れました – LLai

+0

ありがとう@LLai、浅いコピーが動作します。 親コンポーネントでシャローコピーを行う必要がない他の方法があるかどうか疑問に思っていましたか?私は '剣道グリッド'が明白な浅いコピーなしでそれをどうやっているのだろうか。 – cyberpirate92

+0

@cyberpirate92私は剣道グリッドに慣れていませんが、おそらくngOnChangesフックに依存していないでしょう。 (https://plnkr.co/edit/G1dlSJqtcJ9NX7F44zaz?p=preview)このplunkrでは、子コンポーネントがngForで変更を受け取ることがわかります。しかし、あなたのケースでは、あなたのngOnChangesフックに 'extractRowsAndColumns'メソッドがあるので、実行する必要があります。 – LLai

0

を、あなたはこのようなngOnChanges@Input変化を検出することができます

ngOnChanges(changes: SimpleChanges) { 
    for (let propName in changes) { 
     // when your @Input value is changed 
     if(propName === "yourInputName"){ 
     // update the component here 
     } 
    } 
} 

を、それがお役に立てば幸いです。 )

+0

私は 'OnChanges'を実装しましたが、動作しません。 – cyberpirate92

+0

あなたが望むもの: 'data'の値が変更された場合、' extractRowsAndColumns'メソッドを新しい 'data'メソッドで呼び出すことによってコンポーネントを更新しましたか? –

+0

ええ、それは私が欲しいものです。 – cyberpirate92

1

@Input()双方向バインディングを作成してください。

_data; 
@Input() set data(val) { 
    this._data = val; 
} 
get data() { 
    return this._data; 
} 
1

私は前と同じ問題がありました。 ngOnChangesメソッドは、データ型==!の配列の変更のみをリッスンします。

説明(ngOnChanges not firing for nested object):

変化検出角度チェック部品入力変化に対する 特性の間、それは(本質的に)使用===ダーティチェック用。 配列の場合、配列参照(のみ)がダーティチェックされていることを意味します。 rawLapsData配列の参照が変更されていないため、ngOnChanges() は呼び出されません。

+0

あなたが正しいです、子供のデータは実際に更新されていますが、 'ngOnChanges'イベントは起動されません。私は 'setInterval'を使って子コンポーネントにデータを記録しようとしましたが、更新されているのを見ることができました。 – cyberpirate92

関連する問題