2016-11-08 15 views
0

角度コンポーネントについて学習しようとしていますが、ネストされたコンポーネント構成で動作させるのに問題があります。基本的に私がしたいのは、定期的に値を更新する親コンポーネントを持つことです。次に、内部の子コンポーネントを親の値にバインドし、値が変更されたときに$ onChangesを呼び出すようにします。問題を理解する角度コンポーネント

jsFiddle私は達成しようとしていることを実証しました。親コンポーネントが動作していて、更新された値を表示しているようですが、何らかの理由で子コンポーネントがまったくレンダリングされません。

let app = angular.module('app', []); 

class ParentController { 
    constructor($interval) { 
    this.value = 0; 

    $interval(() => this.value++, 1000); 
    } 
} 

let ParentComponent = { 
    controller: ParentController, 
    template: `<div>parent value: {{$ctrl.value}}</div>` 
}; 

app.component('parent', ParentComponent); 

class ChildController { 
    $onChanges(changesObj) { 
    console.log(changesObj); 
    } 
} 

let ChildComponent = { 
    bindings: { 
    value: '=' 
    }, 
    controller: ChildController, 
    require: { 
    parent: '^^parent' 
    }, 
    template: `<div>child value: {{$ctrl.value}}</div>` 
}; 

app.component('child', ChildComponent); 

そしてHTML::

<div ng-app="app"> 
    <parent> 
    <child value="$ctrl.parent.value"></child> 
    </parent> 
</div> 

私が何か間違ったことか、私は不可能を達成しようとしている何であるだろうか?ここで私はこれを達成するために使用していたコードですか

答えて

0

「ng-transclude」ディレクティブを使用しない限り、コンポーネントの中身は通常、置き換えられます。

があなたの子要素が表示されるように取得するには、以下の変更が必要になります。

let ParentComponent = { 
    controller: ParentController, 
    transclude: true, 
    template: `<div>parent value: {{$ctrl.value}}</div><div ng-transclude></div>` 
}; 

を明確にするために、あなたはテンプレート内ng-transcludeディレクティブを持つ要素だけでなく、コンポーネントオブジェクトにtransclude: trueを追加します。 ng-transcludeディレクティブを持つ要素は、<parent>タグの内容に置き換えられます。

これは、あなたの子コンポーネントをレンダリングするために取得します、あなたはまだHTMLを使用して、JavaScriptで、未定義である$scope.$ctrl.parent.valueに相当し、

<child value="$ctrl.parent.value"></child> 

を使用しようとしているということで別のエラーを持っています。

だけに、あなたのHTMLを変更する:に

<div ng-app="app"> 
    <parent> 
    <child></child> 
    </parent> 
</div> 

と子コンポーネント:

let ChildComponent = { 
    controller: ChildController, 
    require: { 
    parent: '^^parent' 
    }, 
    template: `<div>child value: {{$ctrl.parent.value}}</div>` 
}; 

そして、あなたはすべての良いです! (コメントから)

EDIT: 親値の変更は、次のとあなたのChildControllerを交換する必要がありますいつでも更新呼び出しをトリガーするために:これは、子コントローラに時計を追加し

let ChildController = function (scope) { 
    scope.$watch('$ctrl.parent.value', function (newValue, oldValue) { 
    console.log(newValue); 
    }); 
}; 

parent.valueが変更されるたびに関数を呼び出す。

+0

ありがとうございました。私は、transcludeオプションについて知らなかった。親の値が変更されたときにChildComponentに$ onChangesをトリガーさせる方法があるかどうかは分かりますか? – snusnu

+0

私はそれが可能だとは思わない、いいえ。 親コンポーネントのテンプレート内で子コンポーネントが宣言されていない限り、そうではありませんが、私はそれが下りたい道路だとは感じません。 –

+0

私の最後のコメントを無視して、それは確かに可能です。最新の編集を確認してください! –

0

あなたのコードを変更しました。 あなたがやりたいことを達成するための方法は異なります。 ここに私のコードです。私はそれをどうすべきか説明しようとします。私はこのコードサンプルで行った

let app = angular.module('app', []); 

     class ParentController { 
      constructor($interval) { 
      this.value = 0; 

      $interval(() => this.value++, 1000); 
      } 
     } 

     let ParentComponent = { 
      controller: ParentController, 
//here is the important edit. loading child component inside the parent component 
      template: `<div> 
         parent value: {{$ctrl.value}} 
         <child value="$ctrl.value"></child> 
        </div>` 
     }; 

     app.component('parent', ParentComponent); 

     class ChildController { 
      $onChanges(changesObj) { 
      if(changesObj.hasOwnProperty('value')){ 
       this.value=changesObj.value.currentValue //this referes to current scope. 
      } 
      } 
     } 

     let ChildComponent = { 
      bindings: { 
      value: '<' 
      }, 
      controller: ChildController, 
      require: { 
      //parent: '^^parent' no need for this. we will use $onChanges 
      }, 
      template: `<div>child value: {{$ctrl.value}}</div>` 
     }; 

     app.component('child', ChildComponent); 


    <div ng-app="app"><parent></parent></div> 

の事:何がやりたいことは、負荷の子が親の中にあるので、私は親コンポーネントテンプレート 内部のコンポーネントが含まれている

  1. 。親テンプレート内に子を追加しました。

  2. 削除子コンポーネント定義では、子コンポーネントが親コンポーネントに依存するため、削除が必要です。親を使用する必要がある別のユースケースがあります。バインディングと$ onChangesを使用して、親の子供のデータを更新するのが最善です。

  3. は$ onChangesデータにいくつかのバリデーションを追加しました。

    (changesObj.hasOwnProperty( '値')){ this.value = changesObj.value.currentValue }

あなたが変更objが単純な変更オブジェクトであることを理解する必要がある場合

。最初のchange()、現在の値、OldValueなどのような複数のプロパティを持っています。 ここからあなたが望むものを常に検証しなければなりません。 また、現在のスコープである this.valueに設定しています。 親スコープまたはバインドスコープ変数を直接使用していません。私はあなたがデータを表示するために使用する新しいスコープオブジェクトを作成しています。バインディングオブジェクトによって読み込まれます。バインディング

3. $onChangesバインディングを検証し、

this.valueローカルスコープに割り当てて、全体的な、これは 1.parent interval更新両親の範囲に

2. this.valueが起こっている

は子供に渡されます

4.チャイルドテンプレートレンダリングthis.value UI内

関連する問題