Working with $scope.$emit and $scope.$on

前端 未结 12 1236
花落未央
花落未央 2020-11-21 15:22

How can I send my $scope object from one controller to another using .$emit and .$on methods?

function firstCtrl($scop         


        
相关标签:
12条回答
  • 2020-11-21 15:41

    You must use $rootScope to send and capture events between controllers in same app. Inject $rootScope dependency to your controllers. Here is a working example.

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

    Events linked into $scope object just work in the owner controller. Communication between controllers is done via $rootScope or Services.

    0 讨论(0)
  • 2020-11-21 15:41

    Below code shows the two sub-controllers from where the events are dispatched upwards to parent 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/

    0 讨论(0)
  • 2020-11-21 15:45

    To send $scope object from one controller to another, I will discuss about $rootScope.$broadcast and $rootScope.$emit here as they are used most.

    Case 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 are not destroyed automatically. You need to destroy it using $destroy. It is better to use $scope.$on as listeners on $scope are destroyed automatically i.e. as soon as $scope is destroyed.

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

    Or,

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

    Case 2:

    $rootScope.$emit:

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

    The major difference in $emit and $broadcast is that $rootScope.$emit event must be listened using $rootScope.$on, because the emitted event never comes down through the scope tree..
    In this case also you must destroy the listener as in the case of $broadcast.

    Edit:

    I prefer not to use $rootScope.$broadcast + $scope.$on but use $rootScope.$emit+ $rootScope.$on. The $rootScope.$broadcast + $scope.$on combo can cause serious performance problems. That is because the event will bubble down through all scopes.

    Edit 2:

    The issue addressed in this answer have been resolved in angular.js version 1.2.7. $broadcast now avoids bubbling over unregistered scopes and runs just as fast as $emit.

    0 讨论(0)
  • 2020-11-21 15:47

    First of all, parent-child scope relation does matter. You have two possibilities to emit some event:

    • $broadcast -- dispatches the event downwards to all child scopes,
    • $emit -- dispatches the event upwards through the scope hierarchy.

    I don't know anything about your controllers (scopes) relation, but there are several options:

    1. If scope of firstCtrl is parent of the secondCtrl scope, your code should work by replacing $emit by $broadcast in firstCtrl:

      function firstCtrl($scope)
      {
          $scope.$broadcast('someEvent', [1,2,3]);
      }
      
      function secondCtrl($scope)
      {
          $scope.$on('someEvent', function(event, mass) { console.log(mass); });
      }
      
    2. In case there is no parent-child relation between your scopes you can inject $rootScope into the controller and broadcast the event to all child scopes (i.e. also secondCtrl).

      function firstCtrl($rootScope)
      {
          $rootScope.$broadcast('someEvent', [1,2,3]);
      }
      
    3. Finally, when you need to dispatch the event from child controller to scopes upwards you can use $scope.$emit. If scope of firstCtrl is parent of the secondCtrl scope:

      function firstCtrl($scope)
      {
          $scope.$on('someEvent', function(event, data) { console.log(data); });
      }
      
      function secondCtrl($scope)
      {
          $scope.$emit('someEvent', [1,2,3]);
      }
      
    0 讨论(0)
  • 2020-11-21 15:47
    <!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>
    
    0 讨论(0)
  • 2020-11-21 15:48

    I would additionally suggest a 4th option as a better alternative to the proposed options by @zbynour.

    Use $rootScope.$emit rather than $rootScope.$broadcast regardless of the relationship between trasmitting and receiving controller. That way, the event remains within the set of $rootScope.$$listeners whereas with $rootScope.$broadcast the event propagates to all children scopes, most of which will probably not be listeners of that event anyway. And of course in the receiving controller's end you just use $rootScope.$on.

    For this option you must remember to destroy the controller's rootScope listeners:

    var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
    $scope.$on('$destroy', function () {
      unbindEventHandler();
    });
    
    0 讨论(0)
提交回复
热议问题