Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

How can I use HTML5 geolocation in angularjs? I can get it using HTML5; but how can I pass it to angularjs scope in controller? any sample jsfiddle will save my day!

share|improve this question
up vote 26 down vote accepted

you can do something

myApp.controller('fooCtrl', function($scope){
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position){
      $scope.$apply(function(){
        $scope.position = position;
      });
    });
  }
})

you need to do $scope.$apply to trigger the digest cycle when the geolocation arrives and to update all the watchers.

share|improve this answer
    
can u please help me with jsfiddle?? if u dont mind, i am a newbie to angularjs and havent used watch yet. if not, i wont mind :) – AngryJS Apr 20 '14 at 17:52
7  
if you create a skeleton jsfiddle or plunkr i can fill this in, but you have to do some of the work yourself – Vladimir Gurovich Apr 20 '14 at 18:40
    
Sure, will give u skeleton one! thanks! – AngryJS Apr 20 '14 at 18:55
    
it worked as u suggested! thanks! :) – AngryJS Apr 24 '14 at 15:23

I'd suggest abstracting this into a service so your controller doesn't have a dependency on window.navigator, and to avoid the unnecessary use of $scope.$apply(). Here's what I'm using in my project:

angular.module('app', []).factory('geolocationSvc', ['$q', '$window', function ($q, $window) {

    'use strict';

    function getCurrentPosition() {
        var deferred = $q.defer();

        if (!$window.navigator.geolocation) {
            deferred.reject('Geolocation not supported.');
        } else {
            $window.navigator.geolocation.getCurrentPosition(
                function (position) {
                    deferred.resolve(position);
                },
                function (err) {
                    deferred.reject(err);
                });
        }

        return deferred.promise;
    }

    return {
        getCurrentPosition: getCurrentPosition
    };
}]);

Then I consume it in my controller like this:

function captureUserLocation() {
    geolocationSvc.getCurrentPosition().then(onUserLocationFound);
}
share|improve this answer
3  
This should be the answer, it promotes decoupling and shows good use of async programming. – amnesia Jul 22 at 18:28

You can use ngGeolocation. It is simple and does the job.

angular.module('appName', ['ngGeolocation'])
    .controller('appCtrl', function($scope, $geolocation) {
         $geolocation.getCurrentPosition().then(function(position) {
            console.log(position, 'current position');
         });
    });
share|improve this answer

Due to firefox's issue not getting feedback from user on prompting that website needs to access your location when user clicking "Not now", X or outside prompt box (more here), below is a tiny example to trigger fallback action for this case. Plunker

// GeoLocationService
angular.module('myApp').factory('GeoLocationService', function($q, $window, $timeout) {
    var factoryObj = {};

    factoryObj.getPosition = function() {
        var deferred;
        var promiseTimeout = $timeout(function() {
            deferred.reject(1); // return 1 if browser waited for user input for more than timeout delay
        }, 3000);

        deferred = $q.defer();

        if(!$window.navigator.geolocation) { // check if geoLocation is not supported by browser
            $timeout.cancel(promiseTimeout);
            deferred.reject(false); // return false if geoLocation is not supported
        }
        else { // geoLocation is supported
            $window.navigator.geolocation.getCurrentPosition(function(position) {
                $timeout.cancel(promiseTimeout);
                return deferred.resolve(position);
            }, function(error) {
                $timeout.cancel(promiseTimeout);
                return deferred.reject(error.code || 1);
            });
        }

        return deferred.promise;
    };

    return factoryObj;
});

And your app js.

// App
var app = angular.module('myApp', []).controller('myCtrl', function($scope, $log, GeoLocationService) {
    $scope.position = {};

    GeoLocationService.getPosition().then(
        function(position) { // 
            $scope.position = position;
            $log.debug(position);
        },
        function(errorCode) {
            if(errorCode === false) {
                alert('GeoLocation is not supported by browser.');
            }
            else if(errorCode == 1) {
                alert('User either denied GeoLocation or waited for long to respond.');
            }
        }
    );
});
share|improve this answer
    
I wouldn't recommend this approach. It's impossible to pick a timeout duration appropriate for all scenarios, and I wouldn't want to preclude geolocation simply because the visitor didn't answer fast enough. Instead, I'd design my user experience to accommodate not having the user's location, regardless of the reason. And if you really DO want this behavior, I wouldn't put it in the geolocation service; it should go in the controller consuming that service. – Jared Oct 14 at 22:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.