Vartox
Vartox

Reputation: 189

AngularJS: Getting back data with specific id

I'm trying to get a specific product by its id from a JSON file with products. I have some kind of problem as this question AngularJS : get back data from a json array with an id the code is similar. I read through that question and the accepted answer there, still can't figured this out. From what I understand the $scope.search() returns a promise which after success triggers the .then() to set get the correct person.

This line of code prints out the products array and also getting the product id from the url. However it prints out twice in the console.

console.log($scope.products + $routeParams.productId);

app.js

var app = angular.module('gtbApp', [
    'ngRoute',
    'productControllers'
]);

// Setting up the routes with right controllers and partials
app.config(['$routeProvider', function($routeProvider){
    $routeProvider
        .when('/main', {
            templateUrl: 'partials/product-grid.html',
            controller: 'ProductController'
        })
        .when('/product/:productId', {
            templateUrl: 'partials/product-detail.html',
            controller: 'ProductDetailCtrl'
        })
        .otherwise({
            redirectTo: '/main'
        });

}]);

controllers.js

var app = angular.module('productControllers', []);

// For product-grid.html
app.controller('ProductController', ['$http', function($http){
    var store = this;
    store.products = [];    
    $http.get('products.json').success(function(data){
        store.products = data;
    });

}]);

// For product-detail.html
app.controller('ProductDetailCtrl', ['$scope', '$routeParams', '$http', function($scope, $routeParams, $http){

$scope.search = function() {
    var url = 'products.json';
    // Return a promise object
    return $http.get(url).success(httpSuccess).error(function(){
        console.log('Unable to retrieve info form JSON file.');
    });
}

httpSuccess = function(response) {
    $scope.products = response;
}

function getById(arr, id) {
    for (var i = 0, len = arr.length; i < len; i++) {
        if (arr[i].id === id) {
            return arr[i];  
        }
    }
}

$scope.search().then(function(){
    // Prints out the products array and id twice
    console.log($scope.products + $routeParams.productId);
    $scope.product = getById($scope.products, $routeParams.productId);
    // Prints out twice "undefined"
    console.log($scope.product); 
});

}]);

The main question is how to get specific product based on id why in "ProductDetailCtrl"

$scope.product = getById($scope.products, $routeParams.productId); 

doesn't work.

Thanks in advance!

Update: Found out why $scope.product is undefined, it is just because the $routeParams.productId is a string, and in getById() need a integer in second args. However I don't know why console.log($scope.product); prints out twice.

Upvotes: 0

Views: 7267

Answers (2)

m.brand
m.brand

Reputation: 658

You should be either using the .success() and .error() on the $http-promise or only then .then()

Do it like this:

app.controller('ProductController', ['$scope', '$routeParams', '$http', function($scope, $routeParams, $http){

    $scope.search = function() {
        var url = 'products.json';
        // Return a promise object
        return $http.get(url);
    }

    .....

    $scope.search()
        .success(function(data){      // --> data is the products.json
            ... // handle the successfull call
        } );
        .error(function(...) {
            ... // handle the error
        } );

     // or: 

     $scope.search().then(
        function(data){      // --> data is the products.json
            ... // handle the successfull call
        }, 
        function(...) {
            ... // handle the error
        });      

}]);

Upvotes: 0

cbass
cbass

Reputation: 2558

I don't really understand what your main question is here. But anyways. When you use the $http service it will return a promise, which you eventually will have to unwrap. What you are doing in your code is that you are unwrapping it twice. Which is fine.

With $http response you can either use 'success'/'error' or just 'then' which can take a success and an error callback. Which means you could either unwrap in the search function or after you call the search function.

$scope.search = function() {
    var url = 'products.json';
    $http.get(url)
         .success(function(data){
             $scope.product = getById($scope.products, $routeParams.productId);
         })
         .error(function() {
            console.log('Unable to retrieve info form JSON file.');
         });
}

You could also do something like:

$scope.search = function() {
    var url = 'products.json';
    return $http.get(url);
}

$scope.search().then(function(data) {
    $scope.product = getById(data, $routeParams.productId);
}, errorCallback);

And the below would achieve the same result

$scope.search = function() {
    var url = 'products.json';
    return $http.get(url);
}

$scope.search()
      .success(function(data) {
          $scope.product = getById(data, $routeParams.productId);
      })
      .error(errorCallback);

or reference the promise:

$scope.search = function() {
    var url = 'products.json';
    return $http.get(url);
}

var dataPromise = $scope.search();

dataPromise.then(function(data) {
    $scope.product = getById(data, $routeParams.productId);
}, errorCallback);

What you need to know is that as long as you're returning something within a success/error/then function it will return a promise which you will have to unwrap in order to get the data.

Upvotes: 2

Related Questions