it-swarm.com.de

Arbeiten mit $ scope. $ Emit und $ scope. $ On

Wie kann ich mein Objekt $scope mit den Methoden .$emit und .$on von einem Controller zu einem anderen senden?

function firstCtrl($scope) {
    $scope.$emit('someEvent', [1,2,3]);
}

function secondCtrl($scope) {
    $scope.$on('someEvent', function(mass) { console.log(mass); });
}

Es funktioniert nicht so, wie ich es mir vorgestellt habe. Wie funktionieren $emit und $on?

871
Paul Kononenko

Zuallererst spielt die Eltern-Kind-Beziehung eine Rolle. Sie haben zwei Möglichkeiten, ein Ereignis auszulösen:

  • $broadcast - sendet das Ereignis nach unten an alle untergeordneten Bereiche.
  • $emit - Leitet das Ereignis durch die Bereichshierarchie nach oben.

Ich weiß nichts über die Beziehung Ihrer Controller (Bereiche), aber es gibt verschiedene Optionen:

  1. Wenn der Bereich von firstCtrl dem Bereich secondCtrl übergeordnet ist, sollte Ihr Code funktionieren, indem Sie $emit durch $broadcast in firstCtrl ersetzen:

    function firstCtrl($scope)
    {
        $scope.$broadcast('someEvent', [1,2,3]);
    }
    
    function secondCtrl($scope)
    {
        $scope.$on('someEvent', function(event, mass) { console.log(mass); });
    }
    
  2. Falls keine Eltern-Kind-Beziehung zwischen Ihren Bereichen besteht, können Sie $rootScope in den Controller einfügen und das Ereignis an alle untergeordneten Bereiche senden (d. H. Auch secondCtrl).

    function firstCtrl($rootScope)
    {
        $rootScope.$broadcast('someEvent', [1,2,3]);
    }
    
  3. Wenn Sie das Ereignis vom untergeordneten Controller nach oben auslösen müssen, können Sie $scope.$emit verwenden. Wenn der Gültigkeitsbereich von firstCtrl dem Gültigkeitsbereich von secondCtrl übergeordnet ist:

    function firstCtrl($scope)
    {
        $scope.$on('someEvent', function(event, data) { console.log(data); });
    }
    
    function secondCtrl($scope)
    {
        $scope.$emit('someEvent', [1,2,3]);
    }
    
1486
zbynour

Ich würde zusätzlich eine 4. Option als bessere Alternative zu den vorgeschlagenen Optionen von @zbynour vorschlagen.

Verwenden Sie $rootScope.$emit anstelle von $rootScope.$broadcast, unabhängig von der Beziehung zwischen sendendem und empfangendem Controller. Auf diese Weise bleibt das Ereignis in der Menge von $rootScope.$$listeners, wohingegen sich das Ereignis mit $rootScope.$broadcast auf alle untergeordneten Bereiche ausbreitet, von denen die meisten wahrscheinlich sowieso keine Listener dieses Ereignisses sein werden. Und natürlich verwenden Sie am Ende des empfangenden Controllers einfach $rootScope.$on.

Für diese Option müssen Sie daran denken, die rootScope-Listener des Controllers zu zerstören:

var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
$scope.$on('$destroy', function () {
  unbindEventHandler();
});
145
Thalis K.

Wie kann ich mein $ scope-Objekt mit den Methoden. $ Emit und. $ On von einem Controller zu einem anderen senden?

Sie können jedes gewünschte Objekt innerhalb der Hierarchie Ihrer App senden, einschließlich $ scope.

Hier ist eine kurze Vorstellung davon, wie broadcast und emit funktionieren.

Beachten Sie die Knoten unten; alle in Knoten 3 verschachtelt. In diesem Szenario verwenden Sie broadcast und emit.

Anmerkung: Die Anzahl der Knoten in diesem Beispiel ist beliebig. es könnte leicht die Nummer eins sein; die Nummer zwei; oder sogar die Nummer 1.348. Jede Nummer ist nur ein Bezeichner für dieses Beispiel. In diesem Beispiel soll die Verschachtelung von Angular Controllern/Direktiven gezeigt werden.

                 3
           ------------
           |          |
         -----     ------
         1   |     2    |
      ---   ---   ---  ---
      | |   | |   | |  | |

Schauen Sie sich diesen Baum an. Wie beantworten Sie die folgenden Fragen?

Anmerkung: Es gibt andere Möglichkeiten, diese Fragen zu beantworten, aber hier werden wir Sendung und Ausgabe besprechen. Wenn Sie den folgenden Text lesen, nehmen Sie an, dass jede Nummer eine eigene Datei (Direktive, Controller) e.x hat. eins.js, zwei.js, drei.js.

Wie spricht der Knoten 1 mit dem Knoten ?

In der Datei one.js

scope.$emit('messageOne', someValue(s));

In der Datei three.js - der oberste Knoten für alle untergeordneten Knoten, die für die Kommunikation benötigt werden.

scope.$on('messageOne', someValue(s));

Wie spricht Knoten 2 mit Knoten 3?

In der Datei two.js

scope.$emit('messageTwo', someValue(s));

In der Datei three.js - der oberste Knoten für alle untergeordneten Knoten, die für die Kommunikation benötigt werden.

scope.$on('messageTwo', someValue(s));

Wie spricht Knoten 3 mit Knoten 1 und/oder Knoten 2?

In der Datei three.js - der oberste Knoten für alle untergeordneten Knoten, die für die Kommunikation benötigt werden.

scope.$broadcast('messageThree', someValue(s));

In der Datei one.js && two.js welche Datei Sie die Nachricht abfangen möchten oder beides.

scope.$on('messageThree', someValue(s));

Wie spricht Knoten 2 mit Knoten 1?

In der Datei two.js

scope.$emit('messageTwo', someValue(s));

In der Datei three.js - der oberste Knoten für alle untergeordneten Knoten, die für die Kommunikation benötigt werden.

scope.$on('messageTwo', function( event, data ){
  scope.$broadcast( 'messageTwo', data );
});

In der Datei one.js

scope.$on('messageTwo', someValue(s));

JEDOCH

Wenn Sie alle diese verschachtelten untergeordneten Knoten haben, die versuchen, auf diese Weise zu kommunizieren, werden Sie schnell viele $ ons, $ broadcasts und $ emits sehen.

Hier ist was ich gerne mache.

Im obersten ELTERNKNOTEN ( in diesem Fall ...), der Ihr übergeordneter Controller sein kann ...

Also, in der Datei three.js

scope.$on('pushChangesToAllNodes', function( event, message ){
  scope.$broadcast( message.name, message.data );
});

Jetzt müssen Sie in einem der untergeordneten Knoten nur noch $ emit die Nachricht abrufen oder $ on verwenden.

HINWEIS: Es ist normalerweise recht einfach, in einem verschachtelten Pfad zu übersprechen, ohne $ emit, $ broadcast oder $ on zu verwenden, was bedeutet, dass die meisten Anwendungsfälle auftreten, wenn Sie versuchen, den Knoten 1 abzurufen, um mit dem Knoten zu kommunizieren 2 oder umgekehrt.

Wie spricht Knoten 2 mit Knoten 1?

In der Datei two.js

scope.$emit('pushChangesToAllNodes', sendNewChanges());

function sendNewChanges(){ // for some event.
  return { name: 'talkToOne', data: [1,2,3] };
}

In der Datei three.js - der oberste Knoten für alle untergeordneten Knoten, die für die Kommunikation benötigt werden.

Wir haben uns schon darum gekümmert, erinnerst du dich?

In der Datei one.js

scope.$on('talkToOne', function( event, arrayOfNumbers ){
  arrayOfNumbers.forEach(function(number){
    console.log(number);
  });
});

Sie müssen immer noch $ on für jeden bestimmten Wert verwenden, den Sie abfangen möchten, aber jetzt können Sie in jedem der Knoten das erstellen, was Sie möchten, ohne sich Gedanken darüber machen zu müssen, wie die Nachricht über das übergeordnete Element verteilt werden soll Knotenlücke, während wir das generische pushChangesToAllNodes abfangen und senden.

Hoffe das hilft...

109
SoEzPz

Um $scope object von einem Controller zu einem anderen zu senden, werde ich hier auf $rootScope.$broadcast und $rootScope.$emit eingehen, da sie am häufigsten verwendet werden.

Fall 1:

$ rootScope. $ broadcast: -

$rootScope.$broadcast('myEvent',$scope.data);//Here `myEvent` is event name

$rootScope.$on('myEvent', function(event, data) {} //listener on `myEvent` event

$rootScope Listener werden nicht automatisch zerstört. Sie müssen es mit $destroy zerstören. Es ist besser, $scope.$on zu verwenden, da Listener auf $scope automatisch zerstört werden, d. H. Sobald $ scope zerstört wird.

$scope.$on('myEvent', function(event, data) {}

Oder,

  var customeEventListener = $rootScope.$on('myEvent', function(event, data) {

  }
  $scope.$on('$destroy', function() {
        customeEventListener();
  });

Fall 2:

$ rootScope. $ emit:

   $rootScope.$emit('myEvent',$scope.data);

   $rootScope.$on('myEvent', function(event, data) {}//$scope.$on not works

Der Hauptunterschied zwischen $ emit und $ broadcast besteht darin, dass das $ rootScope. $ Emit-Ereignis mit $ rootScope. $ On abgehört werden muss, da das ausgegebene Ereignis niemals über den Gültigkeitsbereichsbaum abfällt..
Auch in diesem Fall müssen Sie den Hörer wie bei $ broadcast zerstören.

Bearbeiten:

Ich bevorzuge es, $rootScope.$broadcast + $scope.$on nicht zu verwenden, sondern $rootScope.$emit+ $rootScope.$on. Die Kombination $rootScope.$broadcast + $scope.$on kann schwerwiegende Leistungsprobleme verursachen. Dies liegt daran, dass das Ereignis alle Bereiche durchströmt.

Edit 2:

Das in dieser Antwort angesprochene Problem wurde in angle.js Version 1.2.7 behoben. $ broadcast vermeidet jetzt das Sprudeln über nicht registrierte Bereiche und läuft genauso schnell wie $ emit.

38
Ved

Sie müssen $ rootScope verwenden, um Ereignisse zwischen Controllern in derselben App zu senden und zu erfassen. Injizieren Sie die Abhängigkeit von $ rootScope in Ihre Controller. Hier ist ein Arbeitsbeispiel.

app.controller('firstCtrl', function($scope, $rootScope) {        
        function firstCtrl($scope) {
        {
            $rootScope.$emit('someEvent', [1,2,3]);
        }
}

app.controller('secondCtrl', function($scope, $rootScope) {
        function secondCtrl($scope)
        {
            $rootScope.$on('someEvent', function(event, data) { console.log(data); });
        }
}

Ereignisse, die mit einem $ scope-Objekt verknüpft sind, funktionieren nur im Besitzer-Controller. Die Kommunikation zwischen Controllern erfolgt über $ rootScope oder Services.

10
kyasar

Sie können einen Dienst von Ihrem Controller aus aufrufen, der ein Versprechen zurückgibt, und ihn dann in Ihrem Controller verwenden. Verwenden Sie außerdem $emit oder $broadcast, um andere Controller darüber zu informieren. In meinem Fall musste ich über meinen Dienst http-Anrufe tätigen, also habe ich Folgendes getan:

function ParentController($scope, testService) {
    testService.getList()
        .then(function(data) {
            $scope.list = testService.list;
        })
        .finally(function() {
            $scope.$emit('listFetched');
        })


    function ChildController($scope, testService) {
        $scope.$on('listFetched', function(event, data) {
            // use the data accordingly
        })
    }

und mein service sieht so aus

    app.service('testService', ['$http', function($http) {

        this.list = [];

        this.getList = function() {
            return $http.get(someUrl)
                .then(function(response) {
                    if (typeof response.data === 'object') {
                        list = response.data.results;

                        return response.data;
                    } else {
                        // invalid response
                        return $q.reject(response.data);
                    }

                }, function(response) {
                    // something went wrong
                    return $q.reject(response.data);
                });

        }

    }])
6
ribhu
<!DOCTYPE html>
<html>

<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var app = angular.module('MyApp',[]);
app.controller('parentCtrl',function($scope){
  $scope.$on('MyEvent',function(event,data){    
    $scope.myData = data;
  });
 });

app.controller('childCtrl',function($scope){
  $scope.fireEvent = function(){ 
  $scope.$emit('MyEvent','Any Data');
  }  
 });
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="parentCtrl" ng-model="myName">

{{myData}}

 <div ng-controller="childCtrl">
   <button ng-click="fireEvent()">Fire Event</button>
 </div>

</div>
</body>
</html>
4
Prashant_M

Das ist meine Funktion:

$rootScope.$emit('setTitle', newVal.full_name);

$rootScope.$on('setTitle', function(event, title) {
    if (scope.item) 
        scope.item.name = title;
    else 
        scope.item = {name: title};
});
4
trai bui

Am Ende habe ich eine externe EventEmitter-Bibliothek hinzugefügt, um sie als Service zu projektieren und dort einzufügen, wo ich sie benötige. So kann ich überall "emittieren" und "weiter", ohne auf die Vererbung des Gültigkeitsbereichs achten zu müssen. Auf diese Weise wird der Aufwand verringert und die Leistung verbessert. Auch lesbarer für mich.

Platzhalter-Unterstützung: EventEmitter2

Gute Leistung: eventemitter

Andere Alternative: Tropf

3

Bereich (e) können verwendet werden, um Ereignisse an untergeordnete oder übergeordnete Bereiche weiterzuleiten oder zu senden.

$ emit - gibt das Ereignis an die Eltern weiter. $ broadcast - überträgt das Ereignis an Kinder. $ on - Methode zum Abhören der Ereignisse, die von $ emit und $ broadcast verbreitet werden.

beispiel index.html :

<div ng-app="appExample" ng-controller="EventCtrl">
      Root(Parent) scope count: {{count}}
  <div>
      <button ng-click="$emit('MyEvent')">$emit('MyEvent')</button>
      <button ng-click="$broadcast('MyEvent')">$broadcast('MyEvent')</button><br>

      Childrent scope count: {{count}} 
  </div>
</div>

beispiel app.js :

angular.module('appExample', [])
.controller('EventCtrl', ['$scope', function($scope) {
  $scope.count = 0;
  $scope.$on('MyEvent', function() {
    $scope.count++;
  });
}]);

Hier können Sie Code testen: http://jsfiddle.net/zp6v0rut/41/

2
Vasyl Gutnyk

Der folgende Code zeigt die beiden Sub-Controller, von denen die Ereignisse nach oben an den übergeordneten Controller (rootScope) gesendet werden.

<body ng-app="App">

    <div ng-controller="parentCtrl">

        <p>City : {{city}} </p>
        <p> Address : {{address}} </p>

        <div ng-controller="subCtrlOne">
            <input type="text" ng-model="city" />
            <button ng-click="getCity(city)">City !!!</button>
        </div>

        <div ng-controller="subCtrlTwo">

            <input type="text" ng-model="address" />
            <button ng-click="getAddrress(address)">Address !!!</button>

        </div>

    </div>

</body>
var App = angular.module('App', []);

// parent controller
App.controller('parentCtrl', parentCtrl);

parentCtrl.$inject = ["$scope"];

function parentCtrl($scope) {

    $scope.$on('cityBoom', function(events, data) {
        $scope.city = data;
    });

    $scope.$on('addrBoom', function(events, data) {
        $scope.address = data;
    });
}

// sub controller one

App.controller('subCtrlOne', subCtrlOne);

subCtrlOne.$inject = ['$scope'];

function subCtrlOne($scope) {

    $scope.getCity = function(city) {

        $scope.$emit('cityBoom', city);    
    }
}

// sub controller two

App.controller('subCtrlTwo', subCtrlTwo);

subCtrlTwo.$inject = ["$scope"];

function subCtrlTwo($scope) {

    $scope.getAddrress = function(addr) {

        $scope.$emit('addrBoom', addr);   
    }
}

http://jsfiddle.net/shushanthp/zp6v0rut/

2

Gemäß der AngularJS-Ereignisdokumentation sollte das empfangende Ende Argumente mit einer Struktur wie enthalten

@params

- {Objekt} Ereignis ist das Ereignisobjekt, das Informationen zum Ereignis enthält

- {Object} Argumente, die vom Angerufenen übergeben werden (Beachten Sie, dass dies immer nur eines sein kann, um ein Dictionary-Objekt zu senden)

$scope.$on('fooEvent', function (event, args) { console.log(args) }); Aus Ihrem Code

Auch wenn Sie versuchen, eine gemeinsame Information über verschiedene Controller verfügbar zu machen, gibt es eine andere Möglichkeit, dies zu erreichen: angular services. Da es sich bei den Diensten um Singletons handelt, können Informationen gespeichert und abgerufen werden Controller. Erstellen Sie einfach Get- und Setter-Funktionen in diesem Service, machen Sie diese Funktionen verfügbar, erstellen Sie globale Variablen im Service und verwenden Sie sie zum Speichern der Informationen

0
Wajih Siddiqui

Der einfachste Weg :

HTML

  <div ng-app="myApp" ng-controller="myCtrl"> 

        <button ng-click="sendData();"> Send Data </button>

    </div>

JavaScript

    <script>
        var app = angular.module('myApp', []);
        app.controller('myCtrl', function($scope, $rootScope) {
            function sendData($scope) {
                var arrayData = ['sam','rumona','cubby'];
                $rootScope.$emit('someEvent', arrayData);
            }

        });
        app.controller('yourCtrl', function($scope, $rootScope) {
            $rootScope.$on('someEvent', function(event, data) {
                console.log(data); 
            }); 
        });
    </script>
0
Sangwin Gawande