32

分離されたスコープを持つディレクティブを書きたいのですが、そのスコープを親スコープのコントローラーで使用できるようにしたいです。私はこの解決策を見つけました:

<div ng-controller="Main">
  <popupbutton directive-scope="popup"></popupbutton>
</div>

app.directive('popupbutton', [function() {
  return {
    restrict:   "E",
    scope:      {    
      directiveScope: "="
    },
    link:       function(sc, el, attrs) {
      sc.directiveScope = sc;
      sc.testvalue = 'foo';
    }
  };  
}]);

app.controller('Main', function($scope) {
  alert($scope.popup.testvalue);  // Where did the property 'popup' come from?!?
});

プランカーを参照してください。

HTML で属性を記述する必要があり、コントローラーのコードでは、スコープ プロパティがどこから来たのかがわからないため、これは少し見苦しいと思います。これを行うより良い方法はありますか?

編集:

その上、コントローラ「メイン」が実行されているときは $scope.popup さえ利用できないようです。ディレクティブのリンク機能がまだ実行されていませんか?

4

1 に答える 1

46

関心事の適切な分離を維持するために、スコープを混在させないでください。同期が難しいことは言うまでもありません。要約すると、ディレクティブは親スコープ (またはそのコントローラー) について何も認識してはならず、コントローラーはディレクティブの内部について何も認識してはなりません。それらは別々のレイヤーの別々のコンポーネントです。

コントローラーとディレクティブの間で通信する適切な方法は、ディレクティブ属性を使用することです。たとえば、ポップアップの場合、これは単純なブール値で実行できます。

コントローラーとディレクティブ:

app.directive('popupbutton', [function() {
  return {
    restrict: "E",
    scope: { isOpen: "=" },
    template: '<a ng-click="isOpen = !isOpen">Toggle</a><div>Open? {{isOpen}}'
  };
}]);

app.controller('MainCtrl', function($scope) {
  $scope.isOpen = false;
});

そしてマークアップ:

<popupbutton is-open="isOpen"></popupbutton>

この方法はロジックを必要とせず、すぐに使用でき、問題の明確な分離を維持します。更新されたプランカーは次のとおりです: http://plnkr.co/edit/otIaGCLmiNdGcYEgi60f?p=preview

于 2013-01-27T06:56:23.047 に答える