Como exigir um controlador em uma diretiva angularjs

Alguém pode me dizer como include um controlador de uma diretiva em outra diretiva angularJS. por exemplo eu tenho o seguinte código

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); } }; }); 

Por todas as contas eu deveria ser capaz de acessar o controlador na diretiva addProduct, mas não estou. Existe um jeito melhor de fazer isso?

Eu tive sorte e respondi isso em um comentário para a pergunta, mas estou postando uma resposta completa por uma questão de completude e assim podemos marcar esta questão como “Respondida”.


Depende do que você deseja realizar compartilhando um controlador; você pode compartilhar o mesmo controlador (embora tenha instâncias diferentes) ou pode compartilhar a mesma instância do controlador.

Compartilhe um controlador

Duas diretivas podem usar o mesmo controlador passando o mesmo método para duas diretivas, da seguinte maneira:

 app.controller( 'MyCtrl', function ( $scope ) { // do stuff... }); app.directive( 'directiveOne', function () { return { controller: 'MyCtrl' }; }); app.directive( 'directiveTwo', function () { return { controller: 'MyCtrl' }; }); 

Cada diretiva terá sua própria instância do controlador, mas isso permite que você compartilhe a lógica entre quantos componentes desejar.

Exigir um controlador

Se você quiser compartilhar a mesma instância de um controlador, use require .

require garante a presença de outra diretiva e, então, inclui seu controlador como um parâmetro para a function de link. Portanto, se você tiver duas diretivas em um elemento, sua diretiva pode exigir a presença da outra diretiva e obter access aos seus methods de controle. Um caso de uso comum para isso é exigir ngModel .

^require , com a adição do cursor, os elementos de verificação acima da diretiva, além do elemento atual, para tentar encontrar a outra diretiva. Isso permite que você crie componentes complexos onde os “subcomponentes” podem se comunicar com o componente pai por meio de seu controlador com grande efeito. Os exemplos podem include guias, onde cada painel pode se comunicar com as guias gerais para lidar com a alternância; um conjunto de acordeão pode garantir que apenas um esteja aberto de cada vez; etc.

Em ambos os casos, você precisa usar as duas diretivas juntas para que isso funcione. require é uma maneira de se comunicar entre os componentes.

Confira a página Guia de diretivas para mais informações: http://docs.angularjs.org/guide/directive

Há uma boa resposta de stackoverflow aqui por Mark Rajcok:

Controladores diretivos AngularJS que exigem controladores diretivos pai?

com um link para este jsFiddle muito claro: http://jsfiddle.net/mrajcok/StXFK/

 

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'; }