ToshNeox
ToshNeox

Reputation: 117

AngularJS not receiving broadcasts in controllers

I'm working on a basic HTML game at the minute, and I have the following page (excluding normal HTML and Angular.js):

<div id="gameContainer" ng-controller="gameController">
    <div id="gameHead">
        <!-- Head bar -->
    </div>
</div>

<div id="debugContainer" ng-controller="debugController">
    <ul id="debugList">
        <li ng-repeat="log in logs">
            <span class="logTime">{{ log.time }}:</span> {{ log.message }}
        </li>
    </ul>
</div>

I have three more JS files defined at the end of the HTML document:

app.js:

var game = angular.module('mystikApp', []);

debugController.js:

game.controller('debugController', ['$rootScope', '$scope', function($rootScope, $scope){
    // Log element
    $scope.logs = [];

    // Padding
    var padZeros = function(i) {
        if (i < 10) {
            i = "0" + i;
        }
        return i;
    }

    $scope.$on('helloWorld', function(e, args){
        alert(args.message);
    });

    // Add a new log entry
    $scope.addLogEntry = function(msg){
        var d = new Date();
        var hour = d.getHours();
        var min = d.getMinutes();
        var time = padZeros(hour) + ':' + padZeros(min);

        var newEntry = {
            message: msg,
            time: time
        };

        $scope.logs.push(newEntry);
    }

    $scope.$on('addLogEntry', function(e, args){
        $scope.addLogEntry(args.message);
        alert('Log entry added, msg: ' + args.message);
    });
}]);

gameController.js:

game.controller('gameController', ['$rootScope', '$scope', function($rootScope, $scope){
    $rootScope.$broadcast('addLogEntry', {message: 'Welcome!'});

    $scope.$emit('helloWorld', {message: 'Hello World!'});
}]);

The JS files are loaded in the order they are listed above, and the second helloWorld 'emit' event is just an attempt to get this working.

The issue

So when the game has loaded (the gameController.js file), I wanted to log a message like 'game loaded' to the log box. For some reason it seems the debug controller never receives the event, and I've looked at all the code samples I could find regarding the use of $broadcast and $emit, and I'm stumped as to why this isn't working now.

I have seen a few people recommending using services in place of this, but I'd rather stick with broadcasting for the minute.

Upvotes: 2

Views: 1325

Answers (2)

Ricardo Velhote
Ricardo Velhote

Reputation: 4690

I removed my whole original answer after reading your comment :)

The code that you have now works perfectly fine if you apply it to an ng-click event for example.

What I see that you want is when the page is loaded to $broadcast the event. The issue here, with your current code, is that the $broadcasts are not being caught because everything (whatever it may be) is not completely loaded yet.

AngularJS has embedded jqLite: a tiny subset of jQuery features. It happens to implement the ready() event which fires when the DOM is completely loaded.

Here is my suggestion:

game.controller('gameController', ['$rootScope', '$scope', function($rootScope, $scope){
    angular.element(document).ready(function () {
        $rootScope.$broadcast('addLogEntry', {message: 'Welcome!'});
        $scope.$apply();
    });
}]);

You have to use $scope.$apply() otherwise when you do $scope.addLogEntry nothing will happen. This is because the ready() is a jqLite event not and AngularJS event. $scope.$apply() will force the digest cycle to run and update your scopes.

Upvotes: 2

jeronimo vallelunga
jeronimo vallelunga

Reputation: 204

here is your problem. When you create a controll width it a new $scope was created. That new $scope is a child of $rootScope.

Knowing that we can say that $broadcast sends events from top to bottom, and $emmit from bottom to top.

So, if you want to communicate controls in the same level you have to $broadcast from a parent level.

game.controller('gameController', ['$rootScope', '$scope', function($rootScope, $scope){
    $rootScope.$broadcast('addLogEntry', {message: 'Welcome!'});
    ....
}]);

Upvotes: 0

Related Questions