0

I've got this snippet of HTML using the Controller As syntax:

<div ng-class="{'hide': !autoDeploy.uiVisibility.overlayLoaderVisible, 'show': autoDeploy.uiVisibility.overlayLoaderVisible}" />

<div ng-class="{'animate-top hide': !autoDeploy.uiVisibility.resultVisible, 'animate-bottom show': autoDeploy.uiVisibility.resultVisible}">

<button ng-click="autoDeploy.btn_extractFormData()">click</button>

with this very stripped down controller:

angular.module("gms.autoDeploy").controller('AutoDeployController', ['$scope', 'AutoDeployService',
    function ($scope, AutoDeployService) {
        var model = this;

        // two-way data binding model to view
        model.uiVisibility = AutoDeployService.getUIVisibility();  

        // Pull the data from our data model arrays
        function btn_extractFormData() {
            AutoDeployService.extractFormData();
        }

        model.btn_extractFormData = btn_extractFormData;
    }
]);

and this segment from my service module:

    var uiVisibility = {
        resultVisible: false,
        overlayLoaderVisible: false
    };
    function getBuildResult() {

        $http({
            url: 'https://jenkins...com/job/...',
            method: 'GET',
            headers: {
                'Accept': "*/*",
                'Authorization': 'Basic ...'
            }
        })
          
            .then(function (res) {
                //stuff happens here
            })

            .catch(function (res) {
                // stuff also happens here
            });
            
        setTimeout(function () {
            uiVisibility.overlayLoaderVisible = false;
            uiVisibility.resultVisible = true;
        }, 1100);

    }

    // return this service (contains the objects that we want to be public)
    return {
        getUIVisibility:                getUIVisibility,
        extractFormData:                extractFormData
    };
}

My issue here is that when the values of uiVisibility.overlayLoaderVisible and uiVisibility.resultVisible are changed in the above setTimeout(), nothing happens on the UI but I know it executes because I've tested it with console logging. If I replace the timeout with just the two lines then they will execute, but it's synchronous, so there's a second or so between each being updated in the view.

My question: Is there some mechanism here preventing the two-way data binding when the value is modified in the async setTimeout() method?

I put the two values into an associative array to account for JavaScript's pass-by-sharing, and works fine with all other objects that I use two-way binding on.

Community
  • 1
  • 1
Darrel Holt
  • 870
  • 1
  • 15
  • 39

1 Answers1

1

Inject the $timeout service into your service, and use that instead. It will trigger a digest for you:

$timeout(function () {
    uiVisibility.overlayLoaderVisible = false;
    uiVisibility.resultVisible = true;
}, 1100);
Frank Modica
  • 10,238
  • 3
  • 23
  • 39
  • That was perfect, thank you. I didn't know that the [$timeout](https://docs.angularjs.org/api/ng/service/$timeout) service was essentially a wrapper for `window.setTimeout` – Darrel Holt Dec 05 '17 at 22:56