rashadb rashadb - 1 month ago 5
AngularJS Question

Using Angular 1.X how can you persist the results of an $http request across controllers?

I've read multiple places that you can share data across controllers with services/providers/factories. Maybe I interpreted the results of these incorrectly but from what I understand services/providers/factories are an abstraction that can be rerun across controllers providing the same data.

I'd like to get result from a database query once without making the same request over again across different controllers. Do services/providers/factories do this or do I need something like ngStorage or localStorage? Or is there another way I'm not thinking of? I saw a mention of making an initial query at start-up (.run?) but I'm not really sure to get started with that.

Answer

To summarise from my comments above...

"I'd like to get result from a database query once without making the same request over again across different controllers. Do services/providers/factories do this..."

Yes. Providers in Angular are singletons so they are all the same instance across the different consumers (controllers, etc). You can store data in them that will last in memory.

A factory only lasts as long as you have the page open and don't reload or navigate away whereas something like local storage persists outside this range.


Here's an example making an HTTP query on app startup (ie, opening / reloading the page) that can be shared across controllers and other consumers

angular.module('so', [])

.factory('sharedData', function($http) {
  // this factory is a promise  
  return $http.get('https://jsonplaceholder.typicode.com/posts/1')
    .then(res => res.data);
})

.controller('someController', function(sharedData) {
  sharedData.then(post => {
    this.post = post;
  });
})

.controller('anotherController', function(sharedData) {
  sharedData.then(post => {
    this.post = post;
  });
});
<div ng-app="so">
  <dl ng-controller="someController as s">
    <dt>Post title</dt>
    <dd>{{s.post.title || 'Loading...'}}</dd>
    <dt>Post body</dt>
    <dd>{{s.post.body || 'Loading...'}}</dd>
  </dl>
  
  <pre ng-controller="anotherController as a">post = {{a.post|json}}</pre>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>