2013-04-24 112 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