AngularJS Geolocation Digest Test

This test shows that the callback from window.navigator.geolocation.getCurrentPosition() doesn't trigger a digest when $scope is updated.

by Seetpal Singh

HTML

<div ng-app>
    <div ng-controller="GeoTestCtrl">
        <div ng-hide="supportsGeo">
            Your browser doesn't support geolocation
        </div>
        <div ng-show="supportsGeo">
            Manual digest when position received: <input type="checkbox" ng-model="manualDigest"/>
            <br/>
            <button ng-click="doTest1()">
                Geo Location Test 1: window.navigator.geolocation
            </button>
            <button ng-click="doTest2()">
                Geo Location Test 2: $window.navigator.geolocation
            </button>
            <hr/>
            Need to type something to trigger digest:
            <input type="text" ng-model="something"/>
            <hr/>
            Position: <button ng-click="position=null">clear</button>
            <pre ng-bind="position|json"/>
        </div>
    </div>
</div>
<hr/>
<div>
    <p>
    This test shows that using the <code>geolocation.getCurrentPosition()</code> callback withing AngularJS prevents message digest from occuring when the $scope is updated inside the callback.
    </p>
    <p>
        I encountered this originally when I abstracted the geolocation into a <code>service</code> that returned a promise so it could do further work on the result before returning. This means that the service needs a <code>$rootScope</code> dependancy to manually trigger the <code>$digest</code>. Since <code>$scope</scope> isn't available to the service unless it is passed in as an argument to the factory instance, <code>$rootScope</code> ensures this isn't forgotten.
    </p>
</div>

CSS

p { padding: .5em 0; }

JavaScript

function GeoTestCtrl($scope, $window) {
    $scope.supportsGeo = $window.navigator;
    $scope.position = null;
    $scope.doTest1 = function() {
        window.navigator.geolocation.getCurrentPosition(function(position) {
            $scope.$apply(function() {
                $scope.position = position;
            });
        }, function(error) {
            alert(error);
        });
    };
    $scope.doTest2 = function() {
        $window.navigator.geolocation.getCurrentPosition(function(position) {
            $scope.$apply(function() {
                $scope.position = position;
            });
        }, function(error) {
            alert(error);
        });
    };

}