Matt Hintzke
Matt Hintzke

Reputation: 8004

How to use an Angular service to share data across controllers/pages?

I am creating a "Web Planner" where the user has to complete a number of steps on different pages in order to create an order for our service. I know that I need to use a service in order to share certain data around the entire Planner, but I am still not sure how do go about it.

The problem is that the user will not necessarily go in-order every time. They can stop on any page, then come back later and resume, therefore I need a way to manage some API data so that if the user is on 1 of 2 pages that share the same data, the data will fetched from the server via API or simply assigned if the data was already taken.

Right now the only method I thought of is to place the API requests inside my Service as well, and then when I run something like OrderService.get() the service will handle logic to check if the data was already grabbed from the server. If it was then it is just a simple assignment like $scope.model = OrderService.get(), but then the problem is that if the data isn't loaded yet, then I need to use a promise somewhere to wait for the data, so a simple assignment operation won't suffice.

This service may look something like this:

app.factory('OrderService', function(){
    var orders = []; // This is the actual data

    var service = {};

    service.get = function(id){
        if(orders.length){
             return orders; // This means there is already data available
        }else{
             // This is where I am not sure what to do...
             // Maybe...
             var promise = API.Orders.getAllOrders({id : id}, function(res){
                    // Not sure about how to implement this part
             }).$promise;

             return promise;
        }
    }


})

Does anyone have any other ideas?

Upvotes: 0

Views: 199

Answers (3)

Joao Leal
Joao Leal

Reputation: 5542

Please bear in mind that I'm still a beginner (reading through a lot of documentation) so this might not be 100% correct.

Your service would be something like this:

app.factory('OrderService', function($q){
    var orders = []; // This is the actual data

    return {
      getData: function(id){
        var deferred = $q.defer();

        if(orders.length){
             deferred.resolve(orders); // This means there is already data available
        }else{
             $http.get('/api/get/data/' + id)
               .success(function(data) {
                  deferred.resolve(data);
               })
               .error(function(){
                  deferred.reject();
               });
        }

        return deferred.promise;
     }
})

And then on your controllers you just need to use it like this:

app.controller('MainCtrl', function($scope, OrderService) {
   var id = 1;
   $scope.data = OrderService.getData(id);
});

Upvotes: 0

SoluableNonagon
SoluableNonagon

Reputation: 11752

Since your calls are asynchronous, the only way to do this is via promises

app.service('OrderService', function($q){ // import $q ; the angularjs promise

    var orders = []; // This is the actual data

    var service = {};

    service.get = function(id){
        var deferred = $q.defer(); // create a unit of work to be done; a promise

        if(orders.length){ // if data is already available, resolve the promise
             deferred.resolve(orders); // This means there is already data available, so mark as resolved and successful
        }else{
             // make your async call since you don't have data
             API.Orders.getAllOrders({id : id}, function(response){
                // here you can actually modify the response before it goes back to your controller
                deferred.resolve(response); 
             }, function(reason){ // failure scenario
                deferred.reject(reason); 
             })

        }
        return deferred.promise; // always return promise
    }
})

Upvotes: 1

alpinescrambler
alpinescrambler

Reputation: 1954

Just return a promise all the time, whether the data is already there, or fetched by a call to a server. In your example..

   if(orders.length){
         return $q.when(orders); // This means there is already data available
    }else{
         // This is where I am not sure what to do...
         // Maybe...
         var promise = API.Orders.getAllOrders({id : id}, function(res){
                // Not sure about how to implement this part
         }).$promise;

         return promise;
    }

Upvotes: 1

Related Questions