Skip to content

Instantly share code, notes, and snippets.

@jeffwhelpley
Last active December 24, 2015 21:29
Show Gist options
  • Save jeffwhelpley/6865807 to your computer and use it in GitHub Desktop.
Save jeffwhelpley/6865807 to your computer and use it in GitHub Desktop.
Idiomatic way in an AngularJS SPA to get data while navigating between pages

Before getting into the AngularJS way of doing things, from a general sense it is best to think of an SPA (single page app) in terms of states and transitions rather than pages and navigation. On the server side when you navigate to a page, all the data needed for that page is gathered at once and rendered in a template before sending the complete response back to the user. SPAs on the other hand can load the important initial data right away but then loading other non-essential data lazily.

In AngularJS that translates to two primary ways of loading data:

  1. Get the important data in the resolve() callback for the state/route transition
  2. Load other data lazily within the Controllers

Resolve

There are two primary ways for users to navigate within an AngularJS SPA. Misko has an example of using resolve() on the AngularJS router here:

http://stackoverflow.com/questions/11972026/delaying-angularjs-route-change-until-model-loaded-to-prevent-flicker

In a similar way you can also use the AngularJS UI Router project (not part of the core, so technically not idiomatic but a great project nonetheless):

http://stackoverflow.com/questions/18004298/angular-ui-router-get-asynchronous-data-with-resolve

Controller Lazy Loading

Within a controller in AngularJS, you can make an API call and save the promise that is returned in the scope.

angular.module('someApp').controller('SomeCntl', function ($scope, PostsModel) {
  $scope.user.posts = PostsModel.getRecentPosts();
});

And then in your template you have something like this:

<ul>
  <li ng-repeat="post in user.posts">{{ title }}</li>
</ul>

The result would be that the template would be rendered and displayed to the user without the posts data loaded initially and then once the promise is fullfilled AngularJS would automatically add all the li elements.

A note on Models

I am doing something in this code which I believe is best practice which is to wrap the backend API calls in custom Models. These Models can use $http or $resource within, but most of the AngularJS code simply uses their intuitive convenience methods (ex. getRecentPosts()). Also, in many cases, you can easily modify the internals of your custom Model objects to utilize the AngularJS $cache and/or $localeStorage so that you don't necessarily go to the back end with each call. There are also libraries like Restangular that provide this type of wrapper Model for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment