2013-04-24 2 views
53

Ich habe Leute gesehenAngularJS: dies zu tun, egal wo in ihrem Code Broadcast-Ereignis von Richtlinie

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

Nun würde Ich mag broacast ein Ereignis aus einer Richtlinie. Ist es eine gute Übung, es auf rootScope-Ebene zu übertragen? Ich möchte dieses Ereignis in einem Controller behandeln. Kann ich $ scope verwenden, oder muss ich noch auf $ rootScope hören?

+0

haben Sie Spielraum in der Richtlinie der Verwendung von isolierten übergeordnete Bereich der Controller –

Antwort

76

In meinem Fall möchte ich nur eine gerade von einer Direktive an den Controller der Ansicht übertragen, in der ich die Richtlinie verwende. Ist es immer noch sinnvoll, Broadcast zu verwenden?

ich die Richtlinie ruft eine Methode auf dem Controller haben würde, die in der HTML angegeben wird, wenn die Richtlinie verwendet wird:

für eine Richtlinie, die einen Isolat Umfang verwendet:

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

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

Für eine Richtlinie, die keinen Isolate-Bereich verwendet:

<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

tatsächlich aktualisieren, mache ich das schon. Aber ich wollte Event-Broadcasting nutzen, weil ich dachte, dass es besser wäre. Ist es nicht in diesem Fall? $ emit und $ on klingen gut :) – Sam

+0

@Sam, ich weiß nicht, welche ist besser zu üben. Ein Ereignis führt zu mehr Kopplung zwischen Ihrer Anweisung und Ihrem Controller, da Ihr Controller auf ein bestimmtes Ereignis warten muss, das von Ihrer Anweisung ausgegeben wird. Ich bevorzuge eine Methode, weil es expliziter/deklarativer ist, dass die Direktive mit dem Controller kommuniziert, und ich kann in meinem HTML erklären, wie das passiert. –

+0

ok, danke für deinen Rat! – Sam

13

Es ist normalerweise eine gute Idee, das $ rootScope nicht zu verwenden, da es global ist und Sie sollten es nicht verschmutzen, wenn Sie nicht wirklich wissen, was Sie tun. Ich würde empfehlen, dass Sie this article about communication between services, directives and controllers lesen.

+1

nach dem Artikel: "Wann immer Sie ein Ereignis in Ihrer Anwendung stattfinden, die alle Controller und Direktiven betrifft". In meinem Fall möchte ich nur eine aus einer Direktive an den Controller übertragene Ansicht, in der ich die Direktive benutze.Ist es immer noch sinnvoll, Broadcast zu verwenden? – Sam

+1

Nein, Sie sollten nicht senden, Broadcasting soll Ereignisse vom übergeordneten Bereich an alle untergeordneten Bereiche senden und Sie gehen anders herum –

+7

Ja, wenn Sie Ereignisse von einem übergeordneten Controller hören möchten, sollten Sie '$ scope. $ emittieren "in der Direktive und" $ Scope. $ on "im übergeordneten Controller – joakimbl

0

Hier ist ein TypeScript-Beispiel für den Aufruf Zurück eine Methode auf dem Controller von einer eingebetteten Direktive. Beachten Sie, dass der Parametername der Anweisung für Ihren Callback einen & definiert, und wenn Sie diesen Callback aufrufen, sollten Sie keine Positionsparameter verwenden, sondern stattdessen ein Objekt mit Eigenschaften verwenden, die die Namen der Parameter im Ziel haben.

die Richtlinie registrieren, wenn Sie Ihre App-Modul zu erstellen:

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

Der Registrierungscode ist wie folgt:

Die Controller der Richtlinie würde wie folgt aussehen

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

Die Der HTML-Code der Anweisung würde in etwa so aussehen:

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

Die Hauptansicht wird wie so

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

eine Instanz der Richtlinie haben nun alles, was Sie auf Ihrem MainController brauchen, ist eine Methode

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

Es gibt so viele Arten, die Sie nicht manuell schreiben müssen ... – Zen

+0

Persönlichen Geschmack :) –

+1

Dies wurde als Vorlage verwendet, um eine Eltern-Controller-Methode aus einer verschachtelten Direktive 2 Ebenen tief aufzurufen. Herzlichen Dank. p.s. Ich denke, Sie haben einen Tippfehler im HTML der Direktive - es sollte controller.fileItemClicked nicht controller.onFileItemSelected sein. –