QuantQandA
QuantQandA

Reputation: 23

Using $scope in AngularJS callbacks

I am trying to bind data to $scope within a callback function and display this in an html element.

Below is my angular code:

gAutocomplete.controller('geocoder', ['gdata', function($scope, gdata){
var geocoder = L.mapbox.geocoder('mapbox.places');
geocoder.query('New York', assign_geocode2());

function assign_geocode2() {
function assign_geocode(err, data) {
    console.log(data);
    $scope.lat = data.latlng[0];
    $scope.lng = data.latlng[1];
    console.log($scope.lat)
}
return assign_geocode;
};

}])

Below is HTML:

</div>
<div class="spacer50"></div>
<div class="center-block" style="width:600px" ng-cloak data-ng-   controller='geocoder'>
  {{"Chosen lat/long are"}} {{$scope.lat}} {{$scope.lng}}
</div>

I can see the controller gets executed, callback function is called and values are written to console.log. However, they are not propogated to HTML element. What could be happening?

Update

I am not using $timeout as below and getting errors that $timeout is not a function. i know I am using an intermediate tmp variable, but when I use $timeout in the closure, I still have the same issue.

gAutocomplete.controller('geocoder', ['$scope', 'gdata', '$timeout',   function($scope, $timeout, gdata) {

    var tmp = {}
    var geocoder = L.mapbox.geocoder('mapbox.places');
    geocoder.query('New York', assign_geocode2(tmp));

    function assign_geocode2(tmp) {
        function assign_geocode(err, data) {
            tmp.lat = data.latlng[0],
            tmp.lng = data.latlng[1]
                        }
        return assign_geocode;
    }

    $timeout(function() {
        $scope.lat = tmp.lat, 
        $scope.lng = tmp.lng, 
            console.log($scope)},0);

}

])

Upvotes: 0

Views: 180

Answers (2)

Mauricio Mau
Mauricio Mau

Reputation: 21

Scope is the glue between application controller and the view. During the template linking phase the directives set up $watch expressions on the scope. The $watch allows the directives to be notified of property changes, which allows the directive to render the updated value to the DOM.

...
{{"Chosen lat/long are"}} {{lat}} {{lng}}
...

Example : http://plnkr.co/edit/5TJJkYf21LlwPyyKjgTv?p=preview

https://docs.angularjs.org/guide/scope

Upvotes: 1

user47589
user47589

Reputation:

You're changing scope values from a non-angular event handler. This means you need to notify angular that, "hey, I've updated things, take note pls". AFAIK the ideal way of taking care of this is running the callback inside a $timeout call.

function assign_geocode(err, data) {
    $timeout(() => {
        console.log(data);
        $scope.lat = data.latlng[0];
        $scope.lng = data.latlng[1];
        console.log($scope.lat)
    });
}

Running this inside $timeout will cause angular to run a digest cycle and update scope values. You don't need to do this from events initiated by Angular, because it already knows its in a digest cycle. For example, services like $http take care of this for you.

Upvotes: 1

Related Questions