Chame o método no controlador de diretriz de outro controlador

Eu tenho uma diretiva que tem seu próprio controlador. Veja o código abaixo:

var popdown = angular.module('xModules',[]); popdown.directive('popdown', function () { var PopdownController = function ($scope) { this.scope = $scope; } PopdownController.prototype = { show:function (message, type) { this.scope.message = message; this.scope.type = type; }, hide:function () { this.scope.message = ''; this.scope.type = ''; } } var linkFn = function (scope, lElement, attrs, controller) { }; return { controller: PopdownController, link: linkFn, replace: true, templateUrl: './partials/modules/popdown.html' } }); 

Isso deve ser um sistema de notificação para erros / notifications / avisos. O que eu quero fazer é de outro controlador (não de uma diretiva) para chamar a function show neste controlador. E quando eu faço isso, eu também quero que minha function de link detecte que algumas propriedades mudaram e executam algumas animações.

Aqui está algum código para exemplificar o que eu estou pedindo:

 var app = angular.module('app', ['RestService']); app.controller('IndexController', function($scope, RestService) { var result = RestService.query(); if(result.error) { popdown.notify(error.message, 'error'); } }); 

Portanto, ao chamar show no controlador de diretiva popdown , a function de link também deve ser acionada e executar uma animação. Como eu poderia conseguir isso?

Essa é uma pergunta interessante, e comecei a pensar em como implementar algo assim.

Eu inventei isso (violino) ;

Basicamente, em vez de tentar chamar uma diretiva de um controlador, criei um módulo para abrigar toda a lógica de pop-up:

 var PopdownModule = angular.module('Popdown', []); 

Eu coloquei duas coisas no módulo, uma factory para a API que pode ser injetada em qualquer lugar e a directive para definir o comportamento do elemento popdown real:

A fábrica apenas define algumas funções de success e error e acompanha algumas variables:

 PopdownModule.factory('PopdownAPI', function() { return { status: null, message: null, success: function(msg) { this.status = 'success'; this.message = msg; }, error: function(msg) { this.status = 'error'; this.message = msg; }, clear: function() { this.status = null; this.message = null; } } }); 

A diretiva obtém a API injetada em seu controlador e observa a API para mudanças (estou usando o bootstrap css por conveniência):

 PopdownModule.directive('popdown', function() { return { restrict: 'E', scope: {}, replace: true, controller: function($scope, PopdownAPI) { $scope.show = false; $scope.api = PopdownAPI; $scope.$watch('api.status', toggledisplay) $scope.$watch('api.message', toggledisplay) $scope.hide = function() { $scope.show = false; $scope.api.clear(); }; function toggledisplay() { $scope.show = !!($scope.api.status && $scope.api.message); } }, template: '
' + ' ' + ' {{api.message}}' + '
' } })

Então eu defino um módulo de app que depende do Popdown :

 var app = angular.module('app', ['Popdown']); app.controller('main', function($scope, PopdownAPI) { $scope.success = function(msg) { PopdownAPI.success(msg); } $scope.error = function(msg) { PopdownAPI.error(msg); } }); 

E o HTML se parece com:

    Succeed Fail   

Não tenho certeza se é completamente ideal, mas parecia uma maneira razoável de estabelecer comunicação com uma diretiva global pop-up.

Mais uma vez, para referência, o violino .

Você também pode usar events para acionar o pop-up.

Aqui está um violino baseado na solução do satchmorun. Ele dispensa o PopdownAPI e, em vez disso, o controlador de nível superior $broadcast os events ‘sucesso’ e ‘erro’ da cadeia de escopo:

 $scope.success = function(msg) { $scope.$broadcast('success', msg); }; $scope.error = function(msg) { $scope.$broadcast('error', msg); }; 

O módulo Popdown, em seguida, registra as funções do manipulador para esses events, por exemplo:

 $scope.$on('success', function(event, msg) { $scope.status = 'success'; $scope.message = msg; $scope.toggleDisplay(); }); 

Isso funciona, pelo menos, e parece-me ser uma solução bem dissociada. Vou deixar os outros gritarem se isso for considerado uma prática ruim por algum motivo.

Você também pode expor o controlador da diretiva ao escopo pai, como o ngForm com o atributo name : http://docs.angularjs.org/api/ng.directive:ngForm

Aqui você pode encontrar um exemplo muito básico de como isso pode ser alcançado http://plnkr.co/edit/Ps8OXrfpnePFvvdFgYJf?p=preview

Neste exemplo eu tenho myDirective com controlador dedicado com o método $clear (uma espécie de API pública muito simples para a diretiva). Eu posso publicar este controlador para o escopo pai e usar chamar esse método fora da diretiva.

Eu tenho uma solução muito melhor.

aqui está minha diretiva, eu injetei na referência do object na diretiva e estendi isso adicionando a function invoke no código da diretriz.

 app.directive('myDirective', function () { return { restrict: 'E', scope: { /*The object that passed from the cntroller*/ objectToInject: '=', }, templateUrl: 'templates/myTemplate.html', link: function ($scope, element, attrs) { /*This method will be called whet the 'objectToInject' value is changes*/ $scope.$watch('objectToInject', function (value) { /*Checking if the given value is not undefined*/ if(value){ $scope.Obj = value; /*Injecting the Method*/ $scope.Obj.invoke = function(){ //Do something } } }); } }; }); 

Declarando a diretiva no HTML com um parâmetro:

  

meu controlador:

 app.controller("myController", ['$scope', function ($scope) { // object must be empty initialize,so it can be appended $scope.injectedObject = {}; // now i can directly calling invoke function from here $scope.injectedObject.invoke(); }];