user2085143
user2085143

Reputation: 4232

AngularJS - Handling API Data

Currently developing an app which requires pulling in data using an API, and running into the following problem.

In my controller I pull in a list of products from an API, add them to $rootScope, than loop over in order to display a list of all products.

When viewing an individual product, I loop over the list and display the product with the requested ID into a view like so

getProduct: function(productID) {
            var products = $rootScope.products;
            for (var i =0; i<products.length; i++) {
            if (products[i].id == parseInt(productID)) {
                return products[i];
                }
           }
        }

This all works fine, except for if you visit the individual product URL without first going through the main list page, the list of products is unavailable as the call to the API is never made.

What is the best way to about resolving this?

Creating another separate API call from this view seems very messy and overly complicated and I was wondering if there is a standard or better approach!

Upvotes: 1

Views: 129

Answers (2)

user2085143
user2085143

Reputation: 4232

Came up with a solution based on your answer (removing the dependency on $rootScope really helped) so marking your answer as good to go but wanted to share what I came up with in case anyone finds it useful!

Essentially, in the product detail controller which deals with displaying an individual product we say, if we already have the product information within the application, pull it from that, and, if we don't then make a call to the API.

I have an extra service called config which I need to access the my API in case anyone is wondering whats going on there :)

Service

productsApp.factory('$productService', function($q,$http,$rootScope,$cookies,$state,$configService) {

var products = '';

return  {
    //Get all products
    getProducts: function() {
        //$http.get....
        //Dont forget to use $q.defer() for your promise
    },
    returnProducts: function() {
        return products;
    },
    //Get specific product
    getProduct: function(productID) {
            for (var i =0; i<products.length; i++) {
            if (products[i].id == parseInt(productID)) {
                return products[i];
                }
            }   
    }
}
});

Controller

productsApp.controller('productDetailCtrl', function($scope,$rootScope,$productService,$stateParams,$configService,$cookies) {

var products = $productService.returnProducts();


if (products == '') {
    $configService.getToken().then(function(response){
            $productService.getProducts().then(function(response){
                $scope.product=$productService.getProduct($stateParams.productID);
            }, function(error){
                console.log(error);
            });
        }, function(error){
            console.log(error);
        });
} else {
    $scope.product = $productService.getProduct($stateParams.jobID);
};
});

Upvotes: 0

Elliott
Elliott

Reputation: 2205

I would create an angular service for product that has a private array for products with a getter & setter. This will allow you to stay away from using $rootScope to pass data between controllers (which is a good thing).

Then have a function that makes a call to the API for each product detail page. You can then pass the ID to the page in the URL using $routeParams

By putting this all in a service it becomes reusable to all your controllers and quite clean.

var myModule = angular.module('myModule', []);
myModule.service('productService', function() {
    var products = [1,2,3,4,5];
    this.addProduct = function(id){
        products.push(id);
    }

    this.getProducts = function(){
        return products;
    }

    this.getProductDetail = function(id){
        //$http.get(...
    }

});

Edit: example implementation as requested

// Don't forget to inject your service into your controller
myModule.controller('myCtrl', ['productService', function (productService) {
    // Add a product to your array
    productService.addProduct(6); //products = [1,2,3,4,5,6]

    // Retrieve products
    var myProducts = productService.getProducts(); //myProducts = [1,2,3,4,5,6]

    // You can do this a few different ways but assuming 
    // getProductDetail returns a promise from its $http call
    productService.getProductDetail(4).then(function (productDetail) {
        $scope.productDetails = productDetail;
    });

}]);

Upvotes: 3

Related Questions