1

AngularJS keeps calling the http get request over and over again!!

If I call getContexts directly in the controller it's fine... but if I call it from the html template, it just keeps calling the get.

Partial contextCtrl.js:

            'use strict';

            app.controller('ContextCtrl', function ContextCtrl($scope, $location, $http, $rootScope, ContextService) {  
                $scope.getContexts = function(keys)
                {
                    $scope.contexts = {};
                    $http.get('/getContextsWS?keys=' + keys).
                    success(function(data){
                      $scope.contexts = data;
                    });
                }

                // This works
                $scope.getContexts('["context::one", "context::two"]')
            });

Partial html section:

            <section id="contextSection" ng-controller="ContextCtrl">

                // This causes get to keep calling!
                {{getContexts('["context::one", "context::two"]')}}

                // Just checking
                {{contexts|json}}

                <nav>
                    <ul ng-show="contexts.length" ng-cloak>
                        <li ng-repeat="context in contexts">
                            <div class="view" ng-click="contextSelected(context)">{{context.name}}</div>
                        </li>
                    </ul>
                </nav>
            </section>

This is driving me nuts!

Okay I've tried your hidden field example and I can't seem to get it to work, but perhaps I'm missing something...

The html:

            <section id="contextSection" ng-controller="ContextCtrl">
            <input type="hidden" ng-model="contextIds" copy-to-model value='@product.item.contextIds'/>

The directive:

            mto.directive('copyToModel', function ($parse) {
                return function (scope, element, attrs) {
                    $parse(attrs.ngModel).assign(scope, attrs.value);
                }
            });

The controller:

            app.controller('ContextCtrl', function ContextCtrl($scope, $location, $http, $rootScope, ContextService) {  

                // I can read this, but it never changes, and without this the contextIds in the alert are null
                $scope.contextIds = "...";

                $rootScope.alert = function(text)
                {
                    alert(text);
                }

                $rootScope.alert("$scope.contextIds: " + $scope.contextIds);

            });

Any idea what am I doing wrong?

1 Answer 1

4

The expressions inside your {{ }} binding code will be re-evaluated anytime Angular notices that something in the model has changed (I've oversimplified what actually occurs). If you want to call getContexts just once don't put it inside {{ }} in your markup and just call it in your controller code.

Basically assume that code inside {{ }} can and will get called multiple times..

So try removing:

// This causes get to keep calling!
{{getContexts('["context::one", "context::two"]')}}

And rely on your controller code (though you might not want getContexts in your scope if you don't call it from your markup):

// This works
$scope.getContexts('["context::one", "context::two"]')
Sign up to request clarification or add additional context in comments.

8 Comments

Hi Gloopy, thanks for the tip! Only starting with AngularJS so still learning... I'm using it with Play 2 Framework so I have something like @(product: models.product.Product) at the start of my template which contains @product.contextIds which I want to pass it to that controller method... So the real code within the template is along the lines of {{getContexts('["@product.item.contextIds.mkString("\", \"")"]')}}
Not sure if this helps (and it's definitely hacky) but if you have data generated on the server side you might be able to copy it to the Angular scope/model (via a directive) and then have your controller retrieve data based on those model values. See this answer for info on this type of directive: stackoverflow.com/a/11839256/1207991. If you could pass the inputs via the url and extract it using $location, $route, or $routeParams that would probably be best.
Thanks for the link... Yeah that seems a bit hacky but perhaps a fallback option. Surely other people have needed to do what I am trying to do, send in some server side values into a controller method? Can you point me to a link re {{ }} being re-evaluated continually? Interested to read more on this...
They aren't re-evaulated continually but during the $digest phase of the scope life cycle. Read more about the data binding dirty checking here. Also see Scope and $digest. In your case I assume the success callback on $http.get setting $scope.contexts kicks off another $digest which processes the watchers (one of which would be your {{getContexts(...)}}) to see if anything has changed that needs to be updated in the view.
That makes sense now, thanks a million for your help... That was really starting to annoy me.
|

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.