I am working on a web store using Angular and am trying to clean the code using a service. I would like the service to load a list of items from a REST api and perform functions on those items across a variety of controllers. My problem occurs when I try to populate an ng-repeat statement with the data returned from the REST call - the list is never populated with the items that are fetched. Previously I was using $scope and $apply to ensure that my DOM was updated when the data was returned - is there something similar that I can do within the service?
The service
'use strict';
var serv = angular.module('serv', []);
serv.factory('shopService', function() {
//create the shop client as service varible
var client = window.ShopifyBuy.buildClient({
domain: 'xxxxxxx.myshopify.com',
storefrontAccessToken: 'xxxxxxxxxxxxxxxxx'
});
var products = [];
client.product.fetchAll().then((products_complete) => {
//do things and get the products ready
products.push(item);
});
return {
products: products
}
});
The controller
'use strict';
var serviceApp = angular.module('serviceApp', ['serv']);
serviceApp.controller('CartController', ['shopService', function CartController(shopService) {
//create a reference to the service variable
this.products = shopService.products;
}]);
And the HTML
<body>
<div ng-app="serviceApp" ng-controller="CartController as cart">
<ul>
<li ng-repeat="product in cart.products">
<div> {{ product.title }} </div>
</li>
</ul>
</div>
</body>
Any help is appreciated.
You can make sure the promise finishes running before assigning the products in the controller and avoid running the fetchAll
more than once. You can change the service:
serv.factory('shopService', function($q) {
//create the shop client as service varible
var client = window.ShopifyBuy.buildClient({
domain: 'xxxxxxx.myshopify.com',
storefrontAccessToken: 'xxxxxxxxxxxxxxxxx'
});
var products = [];
var fetchAllCompleted = false;
function getProducts() {
var deferred = $q.defer();
if (fetchAllCompleted) {
deferred.resolve(products);
} else {
client.product.fetchAll().then((products_complete) => {
//do things and get the products ready
products.push(item);
fetchAllCompleted = true;
deferred.resolve(products);
});
}
return deferred.promise;
}
return {
getProducts: getProducts
}
});
Then in the controller
serviceApp.controller('CartController', ['shopService', function CartController(shopService) {
//create a reference to the service variable
shopService.getProducts().then(function(products) {
this.products = products;
});
}]);
That should fix your issues.