30

私はこれを完全に逆に考えているかもしれませんが、3つのネストされたディレクティブを作成しようとしています。それらを呼び出すことができます:screen、component、widget。ウィジェットがコンポーネントでいくつかの動作をトリガーできるようにしたいのですが、これにより画面でいくつかの動作がトリガーされます。それで:

.directive('screen', function() {
    return {
        scope: true,
        controller: function() {
            this.doSomethingScreeny = function() {
                alert("screeny!");
            }
        }
    }
})

.directive('component', function() {
    return {
        scope: true,
        controller: function() {
            this.componentFunction = function() {
                WHAT.doSomethingScreeny();
            }
        }
    }
})

.directive('widget', function() {
    return {
        scope: true,
        require: "^component",
        link: function(scope, element, attrs, componentCtrl) {
            scope.widgetIt = function() {
                componentCtrl.componentFunction();
            };
        }
    }
})

<div screen>
    <div component>
        <div widget>
            <button ng-click="widgetIt()">Woo Hoo</button>
        </div>
    </div>
</div>

を使用してウィジェットのリンクfnに親コンポーネントを要求できますがrequire: "^component"、コンポーネントコントローラーにその包含画面へのアクセスをさらに許可するにはどうすればよいですか?

必要なのはコンポーネントの内容なので、ウィジェットのボタンをクリックすると「screeny!」と警告されます。

ありがとう。

4

4 に答える 4

36

問題を解決する方法は2つあります。

  1. を使用しているためscope: true、すべてのスコープは通常、継承します。したがって、コントローラーでメソッドをオンでは$scopeなくオンに定義すると、との両方が関数にアクセスできるようになります。 フィドルthisscreencomponentwidgetdoSomethingScreeny
  2. とでリンク関数を定義しcomponentますrequire: '^screen'。リンク関数で、screenCtrlをscopeプロパティに保存すると、ディレクティブのコントローラーでアクセスできます(inject $scope)。
    フィドル
于 2013-03-25T22:00:53.363 に答える
5

コントローラの作成時に親コントローラからプロパティまたはメソッドに直接アクセスする場合、これらのほとんどは失敗します。依存性注入とサービスを使用して、別の解決策を見つけました$controller

.directive('screen', function ($controller) {
    return {
       require: '^parent',
       scope: {},
       link: function (scope, element, attr, controller) {
           $controller('MyCtrl', {
                $scope: scope,
                $element: element,
                $attr, attr, 
                controller: controller
           });
       }
    }
})

.controller('MyCtrl, function ($scope, $element, $attr, controller) {});

この方法は、より適切にテスト可能であり、不要なコントローラーでスコープを汚染することはありません。

于 2015-03-10T15:02:54.583 に答える
0

return {scope:true}またはreturn {scope:false}は、各ディレクティブのコントローラー:function($ scope){}の$ scope変数には影響しませんが、ディレクティブタグはng-controllerまたはng-appタグに入れる必要があります。

JSFiddle

JSFiddle

于 2015-12-02T09:44:38.090 に答える
0

var myApp = angular.module('myApp', [])

.directive('screen', function() {
  return {
    scope: true,
    controller: function() {
      this.doSomethingScreeny = function() {
        alert("screeny!");
      }
    }
  }
})

.directive('component', function() {
  return {
    scope: true,
    controller: function($element) {
      this.componentFunction = function() {
        $element.controller('screen').doSomethingScreeny();
      }
    }
  }
})

.directive('widget', function() {
  return {
    scope: true,
    controller: function($scope, $element) {
      $scope.widgetFunction = function() {
        $element.controller('component').componentFunction();
      }
    }
  }
})

.controller('MyCtrl', function($scope) {
  $scope.name = 'Superhero';
})
<body ng-app="myApp">

  <div ng-controller="MyCtrl">
    <div screen>
      <div component>
        <div widget>
          <button ng-click="widgetFunction()">Woo Hoo</button>
        </div>
      </div>
    </div>
  </div>

</body>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>

画面ディレクティブコントローラで定義された関数に(リンク関数ではなく)コンポーネント$element.controller('screen').doSomethingScreeny()ディレクティブコントローラからアクセスする場合は、 (コンポーネントディレクティブから)を使用できます。

JSFiddle

Angularドキュメント

  • controller(name)-現在の要素またはその親のコントローラーを取得します。デフォルトでは、 ngControllerディレクティブに関連付けられているコントローラーを取得します。nameキャメルケースディレクティブ名として指定されている 場合、このディレクティブのコントローラーが取得されます(例'ngModel')。
于 2016-01-28T15:24:49.967 に答える