0

I'm trying to understand how AngularJS refreshes the information in the browser. With that purpose, I've written a very simple interface, which rests in an AngularJS logic with one controller and one service.

The interface has two input boxes and three buttons:

  • The Input boxes work together with the "Add Text" Button. Whatever is in the input boxes, it is concatenated and show in the "Complete Text" line. This result is not shown in the browser until a manually refresh operation is performed.
  • "Add One" Button, actually performs three operations:
    • Each click adds "1" to the current value of the Integer Variable.
    • Each click concatenates a "a" to the current String Variable.
    • Each click adds "1" to the current value of the Array[0] Variable.
    • The operation to the Array Variabler is shown dynamically in the browser, but the other operations are not shown until a manually refresh operation is performed.
    • Lastly, The "Refresh Fields" button actually performs the manually refresh operation.

I wonder why the variable in the array changes dynamically but the other variable types need a manually operation to load the variable with the current value of the variables in the service.

The html code is:

    <div ng-controller='Refresh as r1'>
  <h3>Variable Refreshing Test</h3> 
  <input type="text" ng-model='r1.texto' placeholder="Write a Text">
  <input type="text" ng-model='r1.addtext' placeholder="Write a text to concatenate">
  <button ng-click='r1.addText();'>Add Text</button>
  <button ng-click='r1.refreshText();'>Refresh Fields</button>
  <button ng-click='r1.addOne();'>Add One</button>
  <div>
    <b>Initial text is:</b> {{r1.texto}}
    <br>
    <b>Current text to add is:</b> {{r1.addtext}}
    <br>
    <b>Complete text is:</b> {{r1.totaltext}}
    <br>
    <b>Integer currently is:</b> {{r1.Integer}}
    <br>
    <b>String currently is:</b> {{r1.String}}
    <br>
    <b>Array currently is:</b> {{r1.Array}}
  </div>

The js code is:

(function() {
    'use strict';
    angular.module('RefreshText', [])
        .controller('Refresh', Refresh)
        .service('Service1', Service1);

    function Refresh($scope, Service1) {
        var refresh = this;
        window.MY_SCOPE = refresh;
        window.listScope = $scope;
        refresh.addText = function() {
            var temp = Service1.addText(refresh.texto, refresh.addtext);
        };
        refresh.refresh.Text = function() {
            refresh.totaltext = Service1.getText();
            refresh.Integer = Service1.getInteger();
            refresh.String = Service1.getString();
            refresh.Array = Service1.getArray();
        };
        refresh.Integer = Service1.getInteger();
        refresh.String = Service1.getString();
        refresh.Array = Service1.getArray();
        refresh.addOne = function() {
            Service1.sumaOne();
        };
    }

    function Service1() {
        var service = this;
        window.ServiceScope = service;
        var text3;
        var varInteger = 1;
        var varString = "a";
        var varArray = [];
        varArray[0] = 1;
        service.addText = function(text1, text2) {
            text3 = text1 + text2;
            return text3;
        };
        service.getText = function() {
            return text3;
        };
        service.getInteger = function() {
            return varInteger;
        };
        service.getString = function() {
            return varString;
        };
        service.getArray = function() {
            return varArray;
        };
        service.sumaOne = function() {
            varInteger++;
            varString = varString + "a";
            varArray[0]++;
        };
    }
})();

The code I've used for the tests is located here: https://github.com/harryangstrom/refreshTest.git.

aug
  • 11,138
  • 9
  • 72
  • 93
  • Hey Larry! Welcome to Stack Overflow! Please give an example of your code here in the question. It will help others to understand better your problem – undefined is our god Aug 27 '18 at 21:50
  • Related: https://stackoverflow.com/questions/16928341/update-parent-scope-variable-in-angular – aug Aug 27 '18 at 22:26

1 Answers1

1

The non-array variables you've got use primitive bindings and AngularJS doesn't automatically update these. If you put these variables behind an object and bind to them via the object instead, any changes to those variables should see them automatically updating in the view.

For example, you can set up your JavaScript like so:

function Refresh($scope, Service1) {
    this.vars = Service1.getVars();
    this.updateVars = Service1.updateVars;
    // ...
}

function Service1() {
    // Note primitives are inside an object
    var vars = { int: 0, str: 'a' };
    this.getVars = function () {
        return vars;
    };
    this.updateVars = function () {
        vars.int += 1;
        vars.str += 'a';
    };
    // ...
}

Then your HTML like so:

<div ng-controller="Refresh as r1">
    <div>{{ r1.vars.int }} {{ r1.vars.str}}</div>
    <button ng-click="r1.updateVars()">Update</button>
</div>
miqh
  • 3,624
  • 2
  • 28
  • 38
  • 1
    To add a bit more color, the reason why primitive types aren't being refreshed is because they are passed by value. The primitive types are: `Boolean, Null, Undefined, Number, String, Symbol (ES6)`. All other types are `Objects`, including Arrays. Objects are passed by reference so the values in both the controller and service reference the same memory address. This is why the digest cycle picks up the change with the Array, but not the changes to the primitive types in the service. – BShaps Aug 27 '18 at 22:46