therebelcoder
therebelcoder

Reputation: 1018

Can't figure out how to use $scope.$watch

If have an application controller. In this controller I call a resource service called "saveGame". The saveGame has a property called "resolved". I initialize this property with false. When the promise resolves (save game is loaded), I set the resolved property to true.

Above part works.

Now I inject the saveGame service in my MainCtrl. If I run the code locally it works, because the saveGame resolves almost instantly. But if I turn on latency - mimicking a very slow connection. The saveGame won't resolve in time and I need to wait for it.

Here is my code:

application
    .controller('MainCtrl',
        ['$scope', 'saveGame', function ($scope, saveGame) {
            'use strict';

            // At this point the savegame should be resolved
            // If not we need to wait for it.
            $scope.$watch(saveGame.resolved, function ( newVal, oldVal) {
                console.log( newVal + '-' + oldVal ); // #1
                if(newVal !== undefined ){
                    //do your stuff here...
                    console.log("do your stuff"); // #2
                }
            });

So the newVal, oldVal at #1 come out as undefined. The console log at #2 never triggers.

For completeness, my saveGame service looks like this:

application
    .factory('saveGame',
        ['$resource', 'config', function ($resource, config) {
            'use strict';

            var _resolved = false;
            var _location = {};

            var _load = function (playerId) {
                var res;
                if (config.getSetting('use-mockup')) {
                    // Use mockup data
                    // $resource returns a class representation
                    res = $resource('data/mockup/savegame/player:id.json');
                } else {
                    // TODO: Use real API
                }
                // This will return a promise!
                return res.get({id: playerId}).$promise;
            };

            var _save = function (stuff) {
                return stuff;
            };

            return {
                load: _load,
                save: _save,
                location: _location,
                resolved: _resolved
            };
        }]);

And the part in my appCtrl like this:

// Load the savegame resource
            var promise = saveGame.load(1); // PlayerId
            promise.then(function (resource) {
                // savegame resource was loaded and resolved
                saveGame.location = resource.location;
                saveGame.resolved = true;
            });

So I know I am doing something wrong, but I just can't figure out what? Same help would be really appreciated.

Upvotes: 1

Views: 68

Answers (1)

Sharikov Vladislav
Sharikov Vladislav

Reputation: 7269

You need this:

        $scope.$watch(function () { return saveGame.resolved; }, function ( newVal, oldVal) {
            console.log( newVal + '-' + oldVal ); // #1
            if(newVal !== undefined ){
                //do your stuff here...
                console.log("do your stuff"); // #2
            }
        });

You have to use string as first parameters of watch or function with return value. If you use string 'a.b.c', AngularJS comparing will compare $scope.a.b.c in current and next cycle. If you use function there, AngularJS will compare result of functions.

May be better way here is to update saveGame service and return promise in it. And everywhere you need result of saveGame you will use this:

module.factory('saveService', ['$http', function ($http) {
    return {
        doSave: function () {
            return $http.get(params);
        }
    }
}])

module.controller('MainCtrl', ['saveService', function (saveService) {
    saveService.doSave().then(function onSuccess() {
        // handle something after save
    });
}])

Upvotes: 1

Related Questions