2

I'm going to get some data from server using $http and JSON response. $http.get() are called after route change. But template are changed before data is downloaded. My goal is:

  • User press a hyperlink in menu, that changes a route,
  • Shows Loading Spinner (DOM Element is in another controller which is on page everytime)
  • Initializing $scope.init() (via ng-init="init()") in controller which is in my new template, this also initializing get data from server
  • Data are downloaded, now I can hide spinner and change visible template

How can I do this? My App looks for example:

Javascript:

var myApp = angular.module('myApp', []);

myApp.controller('MyCtrl', function($scope, $http) {
    $scope.init = function() {
       $http({method: 'GET', url: 'http://ip.jsontest.com/'}).success(function(data) {
           console.log(data);
               $scope.ip = data.ip;
           });
    }
});

myApp.config(function($routeProvider) {

    $routeProvider.when('/link', {
        controller: 'MyCtrl',
        templateUrl: 'embeded.tpl.html'
    });
});

HTML:

<script type="text/ng-template" id="embeded.tpl.html">
    <div ng-controller="MyCtrl" ng-init="init()">
    Your IP Address is: {{ip}}
    </div>
</script>

<div>

    <ul>
        <li><a href="#/link">change route</a></li>
    </ul>

    <div ng-view></div>
</div>
4
  • Have you looked at this thread? stackoverflow.com/questions/17144180/… Commented Dec 21, 2013 at 15:47
  • Yes, but that's not what I need. Commented Dec 21, 2013 at 15:52
  • Why don't you simply send the http request when the controller is constructed, and have a view like <div ng-show="ip">...</div> (i.e. it doesn't show anything until the data is received)? Commented Dec 21, 2013 at 16:01
  • I would rather change the page structure. I don't think ng-view is the best solution for you. Maybe you could work with with ngInclude to change just what you need to update in your page. Have the url change a significant role in your application logic? Do you use some url parameter? Commented Dec 21, 2013 at 17:32

2 Answers 2

6

You need to resolve data before routing happens, thus, move your $http to config section.

This is good tutorial for that, http://www.thinkster.io/pick/6cmY50Dsyf/angularjs-resolve-conventions

This is config part.

 $routeProvider.when('/link', {
    controller: 'MyCtrl',
    templateUrl: 'embeded.tpl.html',
    resolve: {
      data: function ($q, $http) {
        var deferred = $q.defer();
        $http({method: 'GET', url: 'http://ip.jsontest.com/'}).then(function(data) {
          deferred.resolve(data);
        });
        return deferred.promise;
      }
    }
 }

and this is controller part

//`data` is injected from routeProvider after resolved
myApp.controller('MyCtrl', function($scope, $http, data) { 
  $scope.ip = data.ip
});

I think promise in AngularJS is very important concept for any async. processing. You need to use this technique every time you have callback.

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

5 Comments

That's it! But I've a just one question. Is it possible to use ngResource in resolve object?
The question is 'Does ngResource returns promise?'. if so return MyResource.get({id: $route.current.params.id});, if not return MyResource.get({id: $route.current.params.id}).promise;.
My question is, does ngResource can be used in resolve convention :) Just instead $http.get() I want use MyRes.get()
as it said here, stackoverflow.com/a/16759067/454252, return MyRes.get().$promise;
Yes, but I don't need define my resource somewhere (just like in controller)? It looks: Controllers.controller('dashboardCtrl', ['$scope', 'DashboardRes', function($scope, Res) {...}]);. My Resource looks that: app.factory('DashboardRes', ['$resource', function($resource) {...});, without create new variable.
1

I will not do it all for you, however I will point you in the right direction.

First you need the ngRoute module.

var myApp = angular.module('myApp', ['ngRoute']);

And the JS file:

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular-route.js"></script>

Now you routes will be working and you do not need to call a special init function in your controller since they get instanciated on every route change when used with ng-view.

For the spinner, you could add some interceptors to all ajax requests using the $httpProvider. Inside the interceptors you could emit some events on the $rootScope and listen to then in a specialed custom attribute directive e.g. spinner where the magic would occur ;)

Comments

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.