0

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);

}

])

2
  • 2
    double check your DI array... it probably should be gAutocomplete.controller('geocoder', ['$scope', 'gdata', function($scope, gdata){... Commented Sep 14, 2016 at 17:45
  • Thanks. I have now included $scope in DI array. No difference. Commented Sep 14, 2016 at 21:04

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

11 Comments

Thanks @Amy . Do I need to do $scope.apply() anywhere then?
No, $timeout handles that for you. You can, if you so wish, check the scope's current digest "phase" and call apply(), but this is considered an anti-pattern.
"outside of angular context' is another common way of describing it.
you can also just call $scope.$apply() when you're ready to synchronize with the angular runtime. $timeout internally calls $apply(). It's kind of one in the same but I prefer $apply() since it is more intent explicit IMO.
this isn't outside an angular context, it's being called from a function inside the controller, it still has access to $scope through the closures. the real problem here is that '$scope' isn't being imported into the controller properly.
|
1

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

7 Comments

While that is all true, the issue here is scope values are being modified outside of a digest cycle, so none of the watchers will be notified.
You're absolutely right, it's still important to remove the $scope in HTML
No, that isn't important at all.
Actually it is important and its incorrect (although not the only issue at hand)
It's exmaple : plnkr.co/edit/5TJJkYf21LlwPyyKjgTv?p=preview With : {{lat}} {{$scope.lng}}
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.