anglejsディレクティブでコントローラーを要求する方法


86

あるディレクティブのコントローラーを別のangularJSディレクティブに含める方法を教えてもらえますか?たとえば、私は次のコードを持っています

var app = angular.module('shop', []).
config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/', {
        templateUrl: '/js/partials/home.html'
    })
        .when('/products', {
        controller: 'ProductsController',
        templateUrl: '/js/partials/products.html'
    })
        .when('/products/:productId', {
        controller: 'ProductController',
        templateUrl: '/js/partials/product.html'
    });
}]);

app.directive('mainCtrl', function () {
    return {
        controller: function ($scope) {}
    };
});

app.directive('addProduct', function () {
    return {
        restrict: 'C',
        require: '^mainCtrl',
        link: function (scope, lElement, attrs, mainCtrl) {
            //console.log(cartController);
        }
    };
});

すべてのアカウントで、addProductディレクティブでコントローラーにアクセスできるはずですが、そうではありません。これを行うためのより良い方法はありますか?


5
require別のディレクティブの存在を確認してから、そのコントローラーを含めます。^require現在の要素に加えて、現在の要素より上の要素をチェックします。したがって、これを機能させるには、2つのディレクティブを一緒に使用する必要があります。それ以外の場合は、でコントローラーを定義してapp.controllerから、両方のディレクティブで使用します。いずれにせよ、これをHTMLコードと一緒に単純なプランカーに入れることができますか?
Josh David Miller

回答:


187

幸運にも質問へのコメントで回答しましたが、完全を期すために完全な回答を投稿しているので、この質問に「回答済み」のマークを付けることができます。


これは、コントローラーを共有することによって何を達成したいかによって異なります。同じコントローラーを共有することも(インスタンスは異なりますが)、同じコントローラーインスタンスを共有することもできます。

コントローラーを共有する

次のように、2つのディレクティブに同じメソッドを渡すことにより、2つのディレクティブで同じコントローラーを使用できます。

app.controller( 'MyCtrl', function ( $scope ) {
  // do stuff...
});

app.directive( 'directiveOne', function () {
  return {
    controller: 'MyCtrl'
  };
});

app.directive( 'directiveTwo', function () {
  return {
    controller: 'MyCtrl'
  };
});

各ディレクティブはコントローラーの独自のインスタンスを取得しますが、これにより、必要な数のコンポーネント間でロジックを共有できます。

コントローラーが必要

コントローラの同じインスタンスを共有する場合は、を使用しますrequire

require別のディレクティブの存在を確認してから、そのコントローラーをリンク関数のパラメーターとして含めます。したがって、1つの要素に2つのディレクティブがある場合、そのディレクティブは他のディレクティブの存在を要求し、そのコントローラーメソッドにアクセスすることができます。これの一般的な使用例は、を要求することですngModel

^require、キャレットを追加すると、現在の要素に加えてディレクティブの上の要素をチェックして、他のディレクティブを見つけようとします。これにより、「サブコンポーネント」がコントローラーを介して親コンポーネントと通信できる複雑なコンポーネントを作成して、大きな効果を得ることができます。例には、各ペインがタブ全体と通信して切り替えを処理できるタブが含まれる場合があります。アコーディオンセットは、一度に1つだけが開いていることを保証できます。等

いずれの場合も、これを機能させるには、2つのディレクティブを一緒に使用する必要があります。requireコンポーネント間の通信方法です。

詳細については、ディレクティブのガイドページを確認してください:http//docs.angularjs.org/guide/directive


4
兄弟ディレクティブコントローラーを要求することは可能ですか?基本的に、ng-repeatを使用して繰り返される兄弟ディレクティブ間で(同じDOM要素ではなくDOM兄弟のように)コントローラーまたはサービスの同じインスタンスを共有する必要があります。繰り返される各アイテムに、それらの間で共有状態またはロジックを必要とするディレクティブがあると想像してください。
CMCDragonkai 2013

2
@CMCDragonkaiそれを行う方法はありませんが、同じことを達成するための2つの一般的な方法があります。1つ目は、兄弟がすべて同じ「タイプ」である場合、ngRepeatの上の要素はコンテナディレクティブのようになり、すべてのサブ要素は代わりにそのディレクティブを要求でき、すべて同じコントローラーを共有します。より一般的な解決策(そして多くの場合、より標準的なもの)は、共有サービスを使用することです。これらの兄弟が何をし、何を共有する必要があるかについて詳しく説明していただけますか?
Josh David Miller

うん、最初のオプションを実行することになった。コンテナディレクティブコントローラを使用します。よく働く。組積造用です。
CMCDragonkai 2013

これは素晴らしい答えであり、これらすべてがどのように機能するかについての私の理解を固めました。ありがとう!(注として、これは新しい機能かもしれませんがrequire、単一のディレクティブまたはディレクティブの配列を指定するために使用できます。各ディレクティブには^、より詳細な要件のためにキャレット()をプレフィックスとして付けることができます。)
jedd.ahyoung

2つのディレクティブで同じコントローラーを使用しても、各ディレクティブに独自のインスタンスが与えられるわけではありません。
jsbisht 2016

27

MarkRajcokによるスタックオーバーフローの良い答えがここにあります:

親ディレクティブコントローラーを必要とするAngularJSディレクティブコントローラー?

この非常に明確なjsFiddleへのリンク:http://jsfiddle.net/mrajcok/StXFK/

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

JavaScript

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

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

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

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


//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});

function MyCtrl($scope) {
    $scope.name = 'Superhero';
}

4
私にとって、Mark Rajcokの例が最もクリックされたのは、コントローラーメソッドがどのように作成されるかに注意を払うことでした。通常、$ scope.methodName = function(){...}を介して作成されたコントローラーメソッドが表示されますが、これを機能させるには、アクセス可能にするメソッドにthis.methodNameを使用する必要があります。最初は気づかなかった。
coblr 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.