Werken met $scope.$emit en $scope.$on

Hoe kan ik mijn $scope-object van de ene controller naar de andere sturen met behulp van de methoden .$emiten .$on?

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

Het werkt niet zoals ik denk dat het zou moeten. Hoe werken $emiten $on?


Antwoord 1, autoriteit 100%

Allereerst is de relatie tussen ouder en kind van belang. Je hebt twee mogelijkheden om een gebeurtenis uit te zenden:

  • $broadcast— verzendt de gebeurtenis naar beneden naar alle onderliggende bereiken,
  • $emit— verzendt de gebeurtenis omhoog door de bereikhiërarchie.

Ik weet niets over uw controllers (scopes)-relatie, maar er zijn verschillende opties:

  1. Als het bereik van firstCtrlbovenliggend is van het bereik secondCtrl, moet uw code
    werk door $emitte vervangen door $broadcastin firstCtrl:

    function firstCtrl($scope)
    {
        $scope.$broadcast('someEvent', [1,2,3]);
    }
    function secondCtrl($scope)
    {
        $scope.$on('someEvent', function(event, mass) { console.log(mass); });
    }
    
  2. In het geval er geen ouder-kind relatie is tussen uw scopes, kunt u
    kan $rootScopein de controller injecteren en de gebeurtenis uitzenden
    naar alle onderliggende bereiken (d.w.z. ook secondCtrl).

    function firstCtrl($rootScope)
    {
        $rootScope.$broadcast('someEvent', [1,2,3]);
    }
    
  3. Eindelijk, wanneer u de gebeurtenis van de onderliggende controller moet verzenden
    om naar boven te gaan kun je $scope.$emitgebruiken. Als het bereik van firstCtrlbovenliggend is van het bereik secondCtrl:

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

Antwoord 2, autoriteit 10%

Ik zou bovendien een vierde optie willen voorstellen als een beter alternatief voor de voorgestelde opties van @zbynour.

Gebruik $rootScope.$emitin plaats van $rootScope.$broadcastongeacht de relatie tussen verzendende en ontvangende controller. Op die manier blijft de gebeurtenis binnen de set van $rootScope.$$listenersterwijl met $rootScope.$broadcastde gebeurtenis zich verspreidt naar alle onderliggende scopes, waarvan de meeste waarschijnlijk hoe dan ook geen luisteraars zijn van die gebeurtenis. En aan het einde van de ontvangende controller gebruik je natuurlijk gewoon $rootScope.$on.

Voor deze optie moet u eraan denken om de rootScope-luisteraars van de controller te vernietigen:

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

Antwoord 3, autoriteit 7%

Hoe kan ik mijn $scope-object van de ene controller naar de andere sturen met behulp van de .$emit- en .$on-methoden?

U kunt elk gewenst object verzenden binnen de hiërarchie van uw app, inclusief $scope.

Hier is een kort idee over hoe uitzendenen uitzendenwerken.

Let op de onderstaande knooppunten; allemaal genest binnen node 3. Je gebruikt broadcasten emitwanneer je dit scenario hebt.

Opmerking:het nummer van elk knooppunt in dit voorbeeld is willekeurig; het zou gemakkelijk de nummer één kunnen zijn; de nummer twee; of zelfs het getal 1.348. Elk nummer is slechts een identificatie voor dit voorbeeld. Het punt van dit voorbeeld is om het nesten van Angular-controllers/richtlijnen te tonen.

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

Bekijk deze boom. Hoe beantwoord je de volgende vragen?

Opmerking:er zijn andere manieren om deze vragen te beantwoorden, maar hier bespreken we uitzendingen uitzenden. Ga er bij het lezen van onderstaande tekst ook van uit dat elk nummer zijn eigen bestand heeft (richtlijn, controller) e.x. één.js, twee.js, drie.js.

Hoe spreekt knooppunt 1met knooppunt 3?

In bestand one.js

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

In bestand three.js– het bovenste knooppunt voor alle onderliggende knooppunten die nodig zijn om te communiceren.

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

Hoe spreekt knooppunt 2 met knooppunt 3?

In bestand two.js

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

In bestand three.js– het bovenste knooppunt voor alle onderliggende knooppunten die nodig zijn om te communiceren.

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

Hoe spreekt knooppunt 3 met knooppunt 1 en / of knooppunt 2?

In bestand Three.js – het bovenste knooppunt aan alle kinderen knooppunten die nodig zijn om te communiceren.

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

in bestand one.js & amp; & amp; Two.js Want het bestand dat u het bericht of beide wilt opvangen.

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

Hoe spreekt knooppunt 2 met knooppunt 1?

In bestand twee.js

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

In bestand Three.js – het bovenste knooppunt aan alle kinderen knooppunten die nodig zijn om te communiceren.

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

in bestand one.js

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

Echter

Als u al deze geneste kindknooppunten probeert te communiceren, ziet u snel velen $ ON’s , $ Broadcast’s , en $ Emit’s .

Hier is wat ik graag doe.

In het bovenste bovenliggende knooppunt (3 in dit geval …), wat uw ouderregelaar is …

Dus, in bestand three.js

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

Nu hoef je in elk van de onderliggende nodes alleen maar het bericht te $emitof het op te vangen met $on.

OPMERKING:het is normaal gesproken vrij eenvoudig om in één genest pad over te praten zonder $emit, $broadcastof te gebruiken $on, wat betekent dat de meeste gebruiksscenario’s zijn voor wanneer u knooppunt 1probeert te laten communiceren met knooppunt 2of vice versa.

Hoe spreekt knooppunt 2 met knooppunt 1?

In bestand two.js

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

In bestand three.js– het bovenste knooppunt voor alle onderliggende knooppunten die nodig zijn om te communiceren.

We hebben deze al behandeld, weet je nog?

In bestand one.js

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

Je moet nog steeds $ongebruiken voor elke specifieke waarde die je wilt vangen, maar nu kun je alles maken wat je wilt in een van de knooppunten zonder dat je je zorgen hoeft te maken over hoe je het bericht kunt krijgen over de opening van het bovenliggende knooppunt terwijl we de generieke pushChangesToAllNodesopvangen en uitzenden.

Hopelijk helpt dit…


Antwoord 4, autoriteit 3%

Om $scope objectvan de ene controller naar de andere te sturen, zal ik het hebben over $rootScope.$broadcasten $rootScope.$emithier zoals ze het meest worden gebruikt.

Geval 1:

$rootScope.$broadcast:-

$rootScope.$broadcast('myEvent',$scope.data);//Here `myEvent` is event name
$rootScope.$on('myEvent', function(event, data) {} //listener on `myEvent` event

$rootScopeluisteraars worden niet automatisch vernietigd. Je moet het vernietigen met $destroy. Het is beter om $scope.$onte gebruiken omdat luisteraars op $scopeautomatisch worden vernietigd, d.w.z. zodra $scope wordt vernietigd.

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

Of,

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

Geval 2:

$rootScope.$emit:

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

Het belangrijkste verschil tussen $emit en $broadcast is dat de $rootScope.$emit-gebeurtenis moet worden beluisterd met $rootScope.$on, omdat de uitgezonden gebeurtenis nooit door de scope-boom komt..
In dit geval moet je ook de luisteraar vernietigen zoals in het geval van $broadcast.

Bewerken:

Ik gebruik liever niet $rootScope.$broadcast + $scope.$onmaar gebruik
$rootScope.$emit+ $rootScope.$on. De $rootScope.$broadcast +
$scope.$on
combo kan ernstige prestatieproblemen veroorzaken. Dat is
Omdat het evenement door alle scopes zal bubbelen.

bewerken 2 :

Het probleem in dit antwoord is opgelost in Angular.Js
versie 1.2.7. $ broadcast nu vermijdt borrelen over niet-geregistreerde scopes
en loopt net zo snel als $ emit.


Antwoord 5

U moet $ RootScope gebruiken om gebeurtenissen tussen controllers in dezelfde app te verzenden en vastleggen. Injecteer $ Rootscope-afhankelijkheid van uw controllers. Hier is een werkvoorbeeld.

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

Evenementen die zijn gekoppeld aan $ Scope-object werken gewoon in de eigenaarcontroller. Communicatie tussen controllers gebeurt via $ Rootscope of Services.


Antwoord 6

U kunt een service bellen vanuit uw controller die een belofte retourneert en vervolgens in uw controller wordt gebruikt. En verder gebruik $emitof $broadcastom andere controllers erover te informeren.
In mijn geval moest ik HTTP-oproepen door mijn dienst doen, dus ik deed zoiets:

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

en mijn service ziet er als volgt uit

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

Antwoord 7

Dit is mijn functie:

$rootScope.$emit('setTitle', newVal.full_name);
$rootScope.$on('setTitle', function(event, title) {
    if (scope.item) 
        scope.item.name = title;
    else 
        scope.item = {name: title};
});

Antwoord 8

<!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>

Antwoord 9

Bereik(en) kunnen worden gebruikt om gebeurtenissen te verspreiden en te verzenden naar de onderliggende of ouder van het bereik.

$emit– verspreidt de gebeurtenis naar de ouder. $broadcast– verspreidt het evenement naar kinderen.
$on– methode om naar de gebeurtenissen te luisteren, verspreid door $emit en $broadcast.

voorbeeld 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>

voorbeeld app.js:

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

Hier kunt u de code testen:
http://jsfiddle.net/zp6v0rut/41/


Antwoord 10

De onderstaande code toont de twee subcontrollers van waaruit de gebeurtenissen naar boven worden verzonden naar de bovenliggende controller (rootScope)

<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/


Antwoord 11

Volgens de Anguljs-gebeurtenis moeten het ontvangende einde argumenten bevatten met een structuur zoals

@params

— {Object} gebeurtenis is het gebeurtenisobject dat informatie over de gebeurtenis bevat

— {Object} argumenten die worden doorgegeven door de aangeroepene (Merk op dat dit er maar één kan zijn, dus het is beter om altijd een woordenboekobject in te sturen)

$scope.$on('fooEvent', function (event, args) { console.log(args) });
Van je code

Ook als je probeert om een gedeeld stuk informatie beschikbaar te krijgen over verschillende controllers, is er een andere manier om dat te bereiken en dat is hoekige services. Omdat de services singletons zijn, kan informatie worden opgeslagen en opgehaald tussen controllers. maak getter- en setter-functies in die service, leg deze functies bloot, maak globale variabelen in de service en gebruik ze om de info op te slaan


Antwoord 12

De gemakkelijkste manier:

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>

Other episodes