从其他控制器调用指令控制器中的方法

我有一个指令,有自己的控制器。 看下面的代码:

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

这意味着成为错误/通知/警告的通知系统。 我想要做的是从另一个控制器(而不是一个指令)来调用该控制器上的functionshow 。 而当我这样做,我也希望我的链接函数检测到一些属性更改和执行一些animation。

下面是一些代码来说明我所要求的:

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

所以在popdown指令控制器上调用show时,链接函数也应该被触发并执行一个animation。 我怎么能做到这一点?

这是一个有趣的问题,我开始考虑如何实现这样的事情。

我想出了这个(小提琴) ;

基本上,我没有试图从控制器调用指令,而是创build了一个模块来容纳所有的popup式逻辑:

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

我把两件事情放在模块中,一个可以在任何地方注入的API的factory ,以及定义实际popup元素行为的directive

工厂只是定义了一些函数的successerror并跟踪了一些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; } } }); 

该指令获取API注入其控制器,并观察api的变化(我使用引导CSS的方便):

 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: '<div class="alert alert-{{api.status}}" ng-show="show">' + ' <button type="button" class="close" ng-click="hide()">&times;</button>' + ' {{api.message}}' + '</div>' } }) 

然后我定义一个依赖于Popdownapp模块:

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

而HTML看起来像:

 <html ng-app="app"> <body ng-controller="main"> <popdown></popdown> <a class="btn" ng-click="success('I am a success!')">Succeed</a> <a class="btn" ng-click="error('Alas, I am a failure!')">Fail</a> </body> </html> 

我不确定它是否完全理想,但似乎是一个合理的方式来build立沟通与全球ishpopup式指令。

再次,作为参考, 小提琴 。

您也可以使用事件来触发popup窗口。

这是基于satchmorun解决scheme的小提琴 。 它省去了PopdownAPI,而顶层控制器改为在作用域链上$broadcast “成功”和“错误”事件:

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

Popdown模块然后为这些事件注册处理函数,例如:

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

这至less起作用,在我看来这是一个很好的解耦scheme。 如果出于某种原因被认为是不好的做法,我会让别人join。

你也可以将指令的控制器暴露给父范围,就像name ngForm属性一样: http : ngForm : ngForm

在这里你可以find一个非常基本的例子,它可以实现http://plnkr.co/edit/Ps8OXrfpnePFvvdFgYJf?p=preview

在这个例子中,我有myDirective$clear方法专用控制器(sorting非常简单的公共API的指令)。 我可以将此控制器发布到父范围,并使用在该指令外调用此方法。

我有更好的解决scheme。

这里是我的指令,我已经在指令中注入了对象引用,并通过在指令代码中添加invoke函数来扩展该指令。

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

使用参数在HTML中声明指令:

 <my-directive object-to-inject="injectedObject"></ my-directive> 

我的控制器:

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