Joris
Joris

Reputation: 3220

Databinding in angularJS not being updated - UI does not show change in $scope variable

I'm running into a problem with AngularJS where I use a callback on a custom service in order to pass data from one controller to another.

In particular, I'm trying to create a very simple logging service in which one controller registers a listener function with the service to receive updates when a message is logged, and the other controller logs a message when a button in the UI is clicked (triggering the listener in the first controller).

The listener function then updates a $scope.messages variable to show the newly logged message in the UI. However, while the newly arrived message arrives in the listener function, the UI is not updated.

I believe this is because AngularJS is not aware that $scope.messages is being updated. However, trying to wrap the update of $scope.messages with $scope.$apply has brought no avail ($apply already in progress).

HTML Code:

<div ng-app="myApp">
    <div ng-controller="ButtonCtrl">
        <button type="button" ng-click="logMessage()">Button</button>
    </div>
    <div id="console" ng-controller="ConsoleCtrl">
         <div ng-repeat="consoleItem in messages">{{consoleItem.message}}</div>
    </div>
</div>

Javascript Code:

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

module.factory('MyConsole', function($rootScope) {
    var listeners = [];
    var myConsoleService = {};

    myConsoleService.log = function(messageObj) {
      angular.forEach(listeners, function(listener){
             listener(messageObj);
      });
   };

   myConsoleService.registerListener = function(listener) {
      listeners.push(listener);
   };

  return myConsoleService;
});

function ConsoleCtrl($scope, MyConsole){
    $scope.messages = [{"message":"First message!"}];
    MyConsole.registerListener( function(msgObj){
       // while this console.log call below works as expected, the $scope.messages.unshift call does not update the view
       $scope.messages.unshift(msgObj.message);
       console.log($scope.messages);
    });
}

function ButtonCtrl($scope, MyConsole) {
     $scope.logMessage = function () {
        MyConsole.log({message:"myLogmessage"});
     };
}

Code can also be found for your convenience on JSFiddle: http://jsfiddle.net/G5LAY/3/

Any help would be greatly appreciated :-)

Thanks!

Upvotes: 0

Views: 1461

Answers (1)

Anders Ekdahl
Anders Ekdahl

Reputation: 22943

Your code is working, it's just that this line: $scope.messages.unshift(msgObj.message); only adds the message string to $scope.messages when your template expects $scope.messages to be a list of objects instead. So changing it to $scope.messages.unshift(msgObj); should do the trick.

Upvotes: 2

Related Questions