Search code examples
javascriptangularjssocketsangularjs-serviceangularjs-factory

Controller $scope attribute does not update (socket connection)


I want to have my angular controllers get updated by factories connected with websockets.

Factory:

function($rootScope, mySocketFactory) {
    mySocketFactory.setHandler('message', function(event) {
        $rootScope.$apply(function() {
            Factory.msg = event.data;
        });
        console.log('factory', Factory.msg);
    });

    var Factory = {};
    Factory.msg = 'init';
    return Factory;
}

Controller:

function ($scope, myFactory) {
    console.log(myFactory.msg);

    $scope.msg = myFactory.msg;
}

Partial:

<div data-ng-controller="StatusBarController" class="col-lg-12">
    {{msg}}
</div>

If the factory gets data via the message event console.log('factory', Factory.msg); returns the updated value, but the controller does not apply the change and stick to the init data. What am I doing wrong here?

Note: I tried the same example with an array instead of a string and it worked!? First I thought it could be because strings are not passed by reference but since we are in the JS world they are.


Solution

  • Instead of binding a property, you could create a getter function form factory which will return msg property value, the {{msg()}} on html will get evaluated on each digest cycle, as you ran it from your service whenever you are receiving message.

    Factory

    var Factory = {};
    Factory.getMsg = function(){
         return Factory.msg;
    };
    return Factory;
    

    controller

    function ($scope, myFactory) {
        $scope.msg = myFactory.getMsg;
    }
    

    HTML

    <div data-ng-controller="StatusBarController" class="col-lg-12">
        {{msg()}}
    </div>
    

    Update

    Rather than the above way I'd suggest you to follow dot rule, that will need to declare object and that object will have hold on properties Factory.data = {msg : 'init'};` . Once you update the factory variable it will automatically update its reference in your controller variable.

    Factory

    function($rootScope, mySocketFactory) {
        mySocketFactory.setHandler('message', function(event) {
            $rootScope.$apply(function() {
                Factory.data.msg = event.data;
            });
            console.log('factory', Factory.msg);
        });
    
        var Factory = {};
        Factory.data = { msg : 'init'};
        return Factory;
    }
    

    controller

    function ($scope, myFactory) {
        $scope.info = myFactory.data;
    }
    

    HTML

    <div data-ng-controller="StatusBarController" class="col-lg-12">
        {{info.msg}}
    </div>