Search code examples
angularjsservice2-way-object-databinding

AngularJS Bind to Service variables vs service functions?


As an angularJS newbie, I am puzzled by the fact I have to bind to a function returned from the service to update the view, not the data itself, I couldn't find any official document explaining this, Does anyone know why?

JSFiddle Code Sample

<div ng-controller="MyCtrl">
binding to a function works!
    <p ng-bind-html-unsafe="tempLog.returnBuffer()"></p>
    <br><br>
       bind to the service variable: Doesn't work, why?
      <p>log={{tempLog.buffer}}</p>
        <br><br>
    bind to scope var instead of service var, still doesn't work
    <p>log={{logBuffer}}</p>
   bind to a scope var which points to the service Function, works!
            <p>log={{pLogFunc()}}</p>
    <button ng-click="addText('more')">Trace</button><br>
</div>

JS code

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

myApp.factory('myLog', function() {
    var internalBuffer = "";
    return {
        buffer:internalBuffer,
        trace:function(input){
                internalBuffer = internalBuffer + "<br>" +input;
                buff = input;
            },
        returnBuffer:function(){
            return internalBuffer;
        }
    }
});


function MyCtrl($scope, myLog){
    $scope.tempLog = myLog;
    $scope.logBuffer = myLog.buffer;
    $scope.pLogFunc = myLog.returnBuffer;
    myLog.trace("aaa");

    $scope.addText = function(str){
        myLog.trace(str)
    }

}

Solution

  • This is not an AngularJS binding problem, this is just how javascript works. In your service:

    1 buffer is assigned to a primitive variable internalBuffer.

    2 trace() accepts a parameter that changes the internalBuffer primitive

    3 returnBuffer() returns the internalBuffer primitive

    Since trace() changes the internalBuffer primitive, any binding to buffer does not affect the changes in the internalBuffer, furthermore, returnBuffer() returns the value of the internalBuffer so naturally the changes you made with the trace() function affects the return value of the returnBuffer() function.

    Any of these suggestions may work on your end:

    [1] If you want to bind from the buffer property of your myLog service, then change your trace() function to something like this:

    trace:function(input){
      this.buffer = this.buffer + "<br>" +input;
    }
    

    [2] You may disregard the buffer property and solely use the returnBuffer() if youdon't want to expose yourinternalBufferand only use thetrace()to have access in changing theinternalBuffer`

    [3] You can use both, the buffer property provides access to another buffer format while the internalBuffer holds all the private buffers / format / or anything else that you may not want to expose to the users of the service. Just be sure to update the buffer in your trace() function by using this as well.