Jebathon
Jebathon

Reputation: 4581

Angular - unable to call a function located within another controller using $emit and $on

Please see this jsFiddle

In this example I want to create a simple app where if a user presses a button a function in another controller is called. However nothing is happening within the app as $emit isn't being called.

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


app.controller('ControllerOne', function($scope) {

    $scope.$on('foo', function(event, args) {
             alert(args);
         });
});

app.controller('ControllerTwo', function($scope) {

    $scope.call_controller = function () {
    $scope.$emit('foo', 'button was clicked!');    
    }
});

HTML:

<div ng-controller="ControllerOne">
</div>

<div ng-controller="ControllerTwo">
    <button ng-click="call_controller();">Click me</button>
</div>

Upvotes: 1

Views: 405

Answers (3)

Pankaj Parkar
Pankaj Parkar

Reputation: 136194

Though you should use service to communicate between two controller.

I'm explaining why your code isn't working. The reason behind the code is not working is your both the controller are on same hierarchy of DOM. Both the controller are not following any sort of scope inheritance with each other. So you need take help $scope which would be available emit the event to its parent, Instead of using $broadcast, any ways it will reach to $rootScope as its grand parent of all. $rootScope.$on will listen that event.

More pre

ControllerOne

app.controller('ControllerOne', function ($scope, $rootScope) {
    $rootScope.$on('foo', function (event, args) {
        alert(args);
    });
});

ControllerTwo

app.controller('ControllerTwo', function ($scope, $rootScope) {
    $scope.call_controller = function () {
        console.log("clicked");
        $scope.$emit('foo', 'button was clicked!');
    }
});

Working Fiddle

Upvotes: 1

Omri Aharon
Omri Aharon

Reputation: 17064

As others have said, you should use a service to share data between controllers.

But for the sake of learning, emit sends events up the parents, and broadcast sends to child scopes. You have to have a common parent scope to handle this.

So you need something like this:

app.controller('MasterCtrl', function($scope) { 

    // This picks up the event controller two is sending, 
    // and sends another one so controller one will get it    
    $scope.$on('fooEmit', function(event, args) {
         $scope.$broadcast('foo', args);
    });
});

Fiddle

Another option like others have mentioned is to use the $rootScope and keep the master controller out, but my personal preference is to leave the $rootScope untouched as much as possible unless absolutely necessary. Same goes for broadcast/emit, you can probably find another way around it.

Upvotes: 0

aorfevre
aorfevre

Reputation: 5064

Or use a service or use :

For sending the message, broadcast your message from rootScope.

$rootScope.$broadcast('foo', 'button was clicked!');

and $scope.$on to receive

Upvotes: 0

Related Questions