Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DOM isn't refreshing after modifying Angular $scope

I have an HTML5 offline web app that utilizes Angular. I want to build in two buttons. One should check for updates, the other should apply updates.

  • If an update is ready, the Check For Updates button should not be visible, but the Apply Updates button should be.
  • If an update is not ready, the Check For Updates button should be visible, but the Apply Updates button should not be.

I do this logic through a Navigation controller.

TermaPocketBookModule.controller("NavigationController", ['$scope', '$rootScope', function ($scope, $rootScope) {

    //check to see if an update is available when the application starts
    if (window.applicationCache.status === window.applicationCache.UPDATEREADY) {
        $scope.ApplicationUpdateReady = true;
    }
    else {
        $scope.ApplicationUpdateReady = false;
    }

    //add handler to handle the DOM's updateready event.
    window.applicationCache.addEventListener('updateready', function () {
        console.log("Update ready.");
        $scope.ApplicationUpdateReady = true;
    });

    //button handler to apply an update
    $scope.ApplyUpdate = function () {
        console.log("Apply update clicked.");
        window.applicationCache.swapCache();
        location.reload();
    }

    //button handler to check for an update
    $scope.CheckForUpdate = function () {
        console.log("Checking for update.");
        window.applicationCache.update();
    }
}]);

That's wired up in my HTML:

<ul class="nav navbar-nav" ng-controller="NavigationController">
    <li ng-if="ApplicationUpdateReady"><a ng-click="ApplyUpdate()">Update Application</a></li>
    <li ng-if="ApplicationUpdateReady != true"><a ng-click="CheckForUpdate()">Check for Updates</a></li>
</ul>

Here's what actually ends up happening:

  1. I update the app cache manifest on the server.
  2. I push the Check For Updates button in the client. In the JS console I see it pull down the updated resources and I see the log message "Update ready".
  3. At this point, I expect my UI to update and show the Apply Updates button, but it does not. The Check Updates button is still visible, so I click that.
  4. The Update Application button appears. I click that, and it reloads the site properly.

So in Step 3 above, I expect the Update Application button to appear due to changing $scope.ApplicationUpdateReady. Why is that not working and I have to press it a second time to get the Update Application button to appear?

like image 840
mason Avatar asked May 11 '15 21:05

mason


1 Answers

Two things here:

  1. The nature of JavaScript primitives, and the way Angular handles them.
  2. The need for a $scope.$apply on events outside of an Angular digest.

See below:

$scope.model = {};
$scope.model.ApplicationUpdateReady = false;

window.applicationCache.addEventListener('updateready', function () {
    console.log("Update ready.");
    $scope.model.ApplicationUpdateReady = true;
    $scope.$apply();
});

<ul class="nav navbar-nav" ng-controller="NavigationController">
    <li ng-if="model.ApplicationUpdateReady"><a ng-click="ApplyUpdate()">Update Application</a></li>
    <li ng-if="model.ApplicationUpdateReady != true"><a ng-click="CheckForUpdate()">Check for Updates</a></li>
</ul>
like image 192
lucky7id Avatar answered Sep 27 '22 22:09

lucky7id