2013-04-24 110 views
53

广播事件我看到人们在任何地方在他们的代码这样做:AngularJS:从指令

$rootScope.$broadcast('someEvent', someParameter); 

,然后在某些控制器:

$rootScope.$on('someEvent', function(event, e){ /* implementation here */ }); 

现在,我想broacast来自指令的事件。在rootScope级别播放它是否是好习惯?我想在控制器中处理这个事件。我可以使用$ scope,还是必须在$ rootScope上进行监听?

+0

你已经在使用的指令分离范围根据文章,控制器 – 2013-04-24 18:52:06

回答

76

在我的情况下,我只是想从指令中广播一个指令到视图的控制器,其中我使用了指令。那么使用广播还是有意义的吗?

我将具有指令调用控制器,其在所述HTML指定在使用该指令上的方法,包括:

对于使用的分离物范围指令:

<div my-dir ctrl-fn="someCtrlFn(arg1)"></div> 

app.directive('myDir', function() { 
    return { 
    scope: { ctrlFn: '&' }, 
    link: function(scope, element, attrs) { 
     ... 
     scope.ctrlFn({arg1: someValue}); 
    } 

对于不使用隔离示波器的指令:

<div my-dir ctrl-fn="someCtrlFn(arg1)"></div> 

app.directive('myDir', function($parse) { 
    return { 
    scope: true, // or no new scope -- i.e., remove this line 
    link: function(scope, element, attrs) { 
     var invoker = $parse(attrs.ctrlFn); 
     ... 
     invoker(scope, {arg1: someValue}); 
    } 
+0

版本的答案,我已经这么做了。但我想用事件广播,因为我认为这会是更好的练习。这不是在这种情况下吗? $ emit和$对声音不错:) – Sam 2013-04-24 19:35:21

+0

@Sam,我不知道哪个更好练。一个事件导致你的指令和你的控制器之间有更多的耦合,因为你的控制器必须监听你的指令将发出的特定事件。我更喜欢使用一种方法,因为它是更明确/声明性的指令将与控制器进行通信,并且我可以在我的HTML中声明如何发生。 – 2013-04-24 19:43:46

+0

好的,谢谢你的建议! – Sam 2013-04-24 19:48:37

13

通常不建议使用$ rootScope,因为它是全球性的,除非您真的知道自己在做什么,否则不应污染它。我建议你阅读this article about communication between services, directives and controllers

+1

的父范围:“每当您的应用程序中发生影响所有控制器和指令的事件时”。就我而言,我只是想从指令中广播一个指令给视图的控制器,在这个视图中我使用了指令。那么使用广播还是有意义的吗? – Sam 2013-04-24 18:58:06

+1

不,你不应该广播,广播意味着从父范围发送事件到所有子范围,你正在做其他的方法 – 2013-04-24 19:00:22

+7

是的,如果你想听从父控制器的事件,你应该做'$ scope。$在父控制器的指令和'$ scope。$ on'中发射' – joakimbl 2013-04-24 19:06:55

0

这里是一个TypeScript示例如何调用从嵌入式指令返回控制器上的方法。最重要的一点是,回调的指令参数名称在定义时使用&,并且在调用该回调函数时,不应使用位置参数,而应使用具有目标中参数名称的属性的对象。

当你创建你的应用程序模块注册指令:

module MyApp { 
    var app: angular.IModule = angular.module("MyApp"); 
    MyApp.Directives.FileUploader.register(app); 
} 

登记代码如下:

该指令的控制器是这样

module MyApp.Directives.FileUploader { 
    export class Controller { 
     public files: string[] = ["One", "Two", "Three"]; 
     //The callback specified in the view that created this directive instance 
     public onFileItemClicked: (fileItem) => void; 

     // This is the controller method called from its HTML's ng-click 
     public fileItemClicked(fileItem) { 
      //IMPORTANT: Don't use comma separated parameters, 
      //instead use an object with property names to act as named parameters 
      this.onFileItemClicked({ 
       fileItem: fileItem 
      }); 
     } 
    } 
} 

的指令的HTML看起来像这样

<ul> 
    <li ng-repeat="item in controller.files" ng-click="controller.fileItemClicked (item)"> 
    {{ item }} 
    </li> 
</ul> 

主要看有你自己的指令的一个实例,像这样

<body ng-app="MyApp" ng-controller="MainController as controller"> 
    <file-uploader on-file-item-clicked="controller.fileItemClicked(fileItem)"/> 
</body> 

现在,所有你需要在你的MainController是一种方法

public fileItemClicked(fileItem) { 
    alert("Clicked " + fileItem); 
} 
+0

有这么多类型,您不需要手动编写... – Zen 2016-08-10 07:17:06

+0

个人品味:) – 2016-08-10 07:57:00

+1

将此作为模板从嵌套指令调用2级深度的父级控制器方法。多谢。 p.s.我认为你在指令的HTML中有一个输入错误 - 它应该是controller.fileItemClicked而不是controller.onFileItemSelected。 – 2017-02-21 16:44:16