1

I have 2 controllers (Products) and (ProductsFilters) and 1 service (ProductService).

The 2 controllers are being loaded at the same time as the 2nd one (ProductsFilter) acts as a side menu for the first controller (Products).

Products controller calls AJAX service through ProductService and assign the returned data to a variable(Facets) in ProductService.

At same time the the ProductsFilter retrieve the (Facets) from ProductService.

The problem now, that I want to process some data in ProductsFilter controller before it is getting displayed in the view, but at the time of execution, the ProductService.Facets return an empty object because the AJAX call has not been finished yet!

I tried to $watch() the ProductService.Facets but it didn't work.

Here is the product service

.factory('ProductService', function(AppService, CategoryService, $stateParams, $location, $http) {
return {
facets: {},
browse: function(category_id, page, order, order_type) {

  url = AppService.apiUrl() + 'products/browse.json?' + params;

  var that = this;

  return this.getProducts(url).then(function(response) {
    that.facets.grouped_brands = response.grouped_brands;
    that.facets.grouped_categories = response.grouped_categories;
    that.facets.grouped_prices = response.grouped_prices;
    that.facets.grouped_stores = response.grouped_stores;

    return response;
  });

},
getProducts: function(url) {
  return $http.jsonp(url + '&callback=JSON_CALLBACK&ref=mobile_app', {cache: true})
    .then(function(response) {
      if (typeof response.data === 'object') {
        return response.data;
      }
    });
   }
  }
 })

Here is the Products controller:

.controller('ProductsController', function($scope, ProductService) {

  $scope.page = 1;

  $scope.moreProducts = function() {
    ProductService.browse(180, $scope.page)
      .then(function(products) {
        angular.extend($scope.products, products.products);
        $scope.page +=1;
      }
    );
  }

  $scope.products = {}

})

And here is the ProductsFilter controller:

.controller('ProductsFiltersController', function($scope, ProductService) {
  $scope.facets = ProductService.facets;
  $scope.brand_facets = []

  $scope.$watch('facets', function() {
    angular.forEach($scope.facets.grouped_brands, function(value, key) {
      $scope.brand_facets.push({brand: key, count: value})
    });
  });
})
4
  • Can you be more specific about how it didn't work? Could you also provide a code sample of the $watch you tried using? Commented Jun 5, 2014 at 13:51
  • What is your $watch code? I would've suggested that or using $broadcast and $on in your AJAX callback method. Commented Jun 5, 2014 at 13:52
  • Can you post some sample code atleast your Productservice logic Commented Jun 5, 2014 at 13:54
  • @MannyD, Thank you for your comment, I updated the question with the code. Commented Jun 5, 2014 at 21:55

2 Answers 2

1

You can use angulars $broadcast and $on functionality to tell the second controller when the ajax answer is recieved.

How to exactly implement the broadcast feature depends on the relation between your controllers. You can use this SO-answer as help: $scope.$emit and .$on angularJS

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

2 Comments

I tried the $rootScope.$broadcast but it didn't work!
I used $rootScope.$emit() in the service and $rootScope.on() on the controller and it worked fine.
0

It sounds like you have an asynchronous bug in your service. You either need to have the callback of the AJAX request return the data to the controllers, or use the $q to create a promise, which is returned to the controllers.

https://docs.angularjs.org/api/ng/service/$q

$q allows you to create a deferred object. So instead of the service returning a null object, it will return a promise that your controller can act on once it has been fulfilled.

1 Comment

I think an issue with this approach is one controller invokes the service method but the other controller won't know about it without being notified somehow so you'd need a deferred along with some sort of signaling like $watch. Also, assuming this could be called multiple times, you'd need to create and handle multiple deferred's as each one only handles a single resolve, I believe.

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.