Dismiss
Announcing Stack Overflow Documentation

We started with Q&A. Technical documentation is next, and we need your help.

Whether you're a beginner or an experienced developer, you can contribute.

Sign up and start helping → Learn more about Documentation →

Working on a application that requires multiple components to be displayed on the same page that need data from the same api url.

As per example I have two components, one is a breadcrumb one is the actual data container and both of them will request the status of a component in order to display relevant data.

data factory

angular
    .module('app')
    .factory('data', function($http) { 
        this.getStatus = function() {
            return $http.get('/api/status/');
        }

        return this;
    });

controller 1

angular
    .module('app')
    .controller('breadcrumb', function(data, breadcrumbProcessor) {
         var _self = this;

         data
             .getStatus()
             .then(function(response) {
                 _self.activeBreadcrumb = breadcrumbProcessor(response.data); 
             });
    });

controller 2

angular
    .module('app')
    .controller('form', function(data, formProcessor) {
         var _self = this;

         data
             .getStatus()
             .then(function(response) {
                 _self.activeForm = formProcessor(response.data); 
             });
    });

The first component will be a breadcrumb that shows the stage of the process while the second component will be a page where you show a form depending on the stage. So I will call for both components the same api "GET:/api/stage/" which will case 2 requests to be made to the server.

Is it possible (and if so how would it look like) to make an interceptor or service that acts like a filter for the requests and merges them into a single request?

share|improve this question
    
In my opinion, this question cannot be answer unless: (1) You explain in a clear way why do you need two requests at all and (2) who is the one that receives the requests (meaning what is running at your server side). – FDavidov Aug 4 at 12:05

Blitz, why you page controller cant make the call for this two components and send the data to your components ?

I mean, you need to have a controller which use your data factory. Then you pass the data by scope to your breadcrumb component/directive as same as your form. Something like this :

angular.module('myApp')
  .controller('ParentController', function (data, $scope) {
    data.getStatus()
             .then(function(response) {
                 $scope.yourData = response.data; 
             });
  })
  .directive('breadcrumb',   function () {
    return {
      restrict: 'A',
      replace: true,
      transclude: false,
      scope: {
        yourData: '='
      },
      templateUrl: 'directives/breadcrumb.html',
      link: function(scope){
        scope.$watch('yourData', function (newValue) {
          scope.activeBreadcrumb = breadcrumbProcessor(newValue);
        });
      }
    };
  })
  .directive('yourForm',   function () {
    return {
      restrict: 'A',
      replace: true,
      transclude: false,
      scope: {
        yourData: '='
      },
      templateUrl: 'directives/your-form.html',
      link: function(scope){      
        scope.$watch('yourData', function (newValue) {
          scope.activeForm = formProcessor(newValue);
        });
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="ParentController">
  <breadcrumb your-data="yourData" />
  <your-form your-data="yourData" />  
</div>

share|improve this answer

You can also just use your factory differently to get the stored data if it's available:

angular
  .module('app')
  .factory('data', function($http) {
    var vm = this;

    // save to inner variables. those are not
    // accessible from outside the factory
    var statusPromise = $q.defer();

    vm.status = deferred.promise;

    // now, the data is fetched when this factory is
    // initialized (included somewhere)
    $http.get('/api/status/').then(function(res) {
      statusPromise.resolve(res.data);
    });

    return vm;
});

This way, you always get a promise when requesting the status. if $http already finished, this will return a resolved promise. if not, this will still return a promise (that will get resolved later).

This means that once this factory is initialized, the data is fetched. If you don't want that behaviour, you can create a getStatus function with the following syntax:

this.getStatus = function() {
  if (!vm.promiseResolvedAlready) {
    $http.get('/api/status/').then(function(res) {
      statusPromise.resolve(res.data);
      vm.promiseResolvedAlready = true;
    });
  }

  return vm.status;
}

and remove the inline $http request. That way, the first time someone calls getStatus, the status will actually update the promise. Up until that point, the promise will remain unresolved.

share|improve this answer
up vote 0 down vote accepted

fixed it using the angular http cache as stated in docs.angularjs.org/api/ng/service/$http.

I have a http interceptor that I use to inject the auth token and there I set cache = true only for GET requests.

So now, my interceptor has something like

function request(config) {

    ...

    if(config.method == "GET") {
        config.cache = true;
    }

    ...
}

and that seems to do the trick just right.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.