简体   繁体   中英

Emitting data across controllers

I was trying to follow this exampled provided by the Angular creator Vojta. However, I can't seem to get the emit to work properly. Here is my fiddle: http://jsfiddle.net/nopctoday/fp2y3jur/2/

<div ng-module="myapp">
    <div ng-controller="ControllerZero">
        <button ng-click="pass_data()">BROADCAST</button>
    </div>

    <div ng-controller="ControllerOne">
        {{data}}
    </div>
</div>

and the simple js

var myModule = angular.module('myapp', []);

app.controller('ControllerZero',['$scope',function($scope){
    $scope.pass_data = function() {
        $scope.$emit('broadcasting', 'it succeeded!');
    };
}]);

app.controller('ControllerOne',['$scope', function($scope){
    $scope.data = "";
    $scope.$on('broadcasting', function(event, data) {
        $scope.data = data;
    });
}]);

$emit bubbles the event upwards the scope hierarchy, including the current scope.

$broadcast sends the event downwards the scope hierarchy, including the current scope.

In your case, the scope of ControllerZero and the scope of ControllerOne are siblings, so $scope.$emit doesn't reach the sibling scope.

Depending on the variety of listeners that you intend to reach, you could either do:

#1

$scope.$root.$emit("eventName", ...); // or $rootScope

that will reach listeners of $rootScope :

$rootScope.$on("eventName", ...)

or, #2 , you could broadcast from the root:

$scope.$root.$broadcast("eventName", ...)

that will reach all listeners

$scope.$on("eventName", ...)

You seem to have some typos in your code. Also the 2 controllers so not share the same scope. So if you want to broadcast events between them you need to use the root scope:

var app = angular.module('myapp', []);

app.controller('ControllerZero', ['$scope', function($scope) {
    $scope.pass_data = function() {
        $scope.$emit('broadcasting', 'it succeeded!');
    };
}]);

app.controller('ControllerOne', ['$scope', '$rootScope', function($scope, $rootScope) {
    $scope.data = null;
    $rootScope.$on('broadcasting', function(data, args) {
        $scope.data = args;
    });
}]);

and here's a sample fiddle: http://jsfiddle.net/3epo5ckz/1/

In this case, the issue is that $emit sends events up the scope chain. Its companion, $broadcast , sends things down the scope chain. The example you provided seems like it would only work in some cases. The way I've accomplished this in the past is like this:

ctrlOne.js

angular.module('app').controller(function($rootScope) {
  $rootScope.$broadcast('broadcasting', 'message');
});

ctrlTwo.js

angular.module('app').controller(function($scope) {
  $scope.$on('broadcasting', function(msg) {
    // should output 'message'
    console.log(msg);
  });
});

You could also alias this process with some service like this:

messenger.service.js

angular.module('app').factory(function($rootScope) {
  return {
    send: $rootScope.$broadcast,
    on: $rootScope.$on
  };
}

You can read Angular's documentation on $on , $emit , and $broadcast .

If you have a large application and don't want to pollute it with messages from the root scope you can also use your parent to broadcast. That way only your sibling and child controllers will receive the event.

$scope.$parent.$broadcast("eventName", ...);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM