How do I pass data to my factory properly using ngRoute and ngResource?

I'm new to Angular and still learning. I have an angular ecommerce app I'm building.

I have a category partial and a product partial. I'm using `ng-view` and `$routeProvider` for the navigation.

What I'm unable to figure out is how to pass this `PartNumber` to my product service factory in order to get the details. I'm not sure I setup the factory right.  

Here's my controller:

    var unarcoQS = angular.module('unarcoQS',['ngResource', 'ngCart', 'ngRoute', 'angular.filter']);

    // Factories
    unarcoQS.factory('categoryService', function ($resource) {
      return $resource('http://example.com:7444/api/products/', {});
    });

    unarcoQS.factory('productService', function ($resource) {
      return $resource('http://example.com:7444/api/products/:PartNumber',{PartNumber: "@PartNumber"});
    });

    unarcoQS.config(['$routeProvider', '$locationProvider',
      function($routeProvider, $locationProvider){
        $routeProvider
        .when('/',{
          templateUrl:'template/home.html', 
          controller: "homeCtrl"
        })
        .when('/category/',{
          templateUrl:'template/category.html', 
          controller: "catCtrl"
        })
        .when('/product/:PartNumber', {
          templateUrl: 'template/product.html',
          controller: ['$routeParams', function($routeParams) {
                          var self=this;
                          self.id = $routeParams;
                          return $routeParams;
                      }],
          controllerAs: 'prodCtrl'
        })
        .otherwise({redirectTo:'/'});

        // console.log($routeParams);
        $locationProvider.html5Mode(false);
    }]);

    // Controllers
    unarcoQS.controller ('homeCtrl', ['$scope', 'productService', 'ngCart', '$filter', function($scope, productService, ngCart) {

    }]); //end homeCtrl

    unarcoQS.controller ('catCtrl', ['$scope', 'categoryService', 'ngCart', '$filter', function($scope, categoryService, ngCart) {
      ngCart.setTaxRate(7.5);
      ngCart.setShipping(2.99);

      var queryParams = {};
      categoryService.query(queryParams, {}, function (response) {
        $scope.products = response;
      });

      $scope.filtering = function(filter){
        $scope.catFilter = filter;
        // console.log(filter);
      };
    }]); //end catCtrl


    unarcoQS.controller ('prodCtrl', ['$scope', 'productService', 'ngCart', '$route', '$routeParams', '$resource', function($scope, productService, ngCart, $route, $routeParams, $resource) {
      id = $routeParams.PartNumber
      $scope.product = productService.get({PartNumber: id});

      console.log($scope.product);

    }]); //end prodCtrl

Open in new window


Here's a link to the demo:
http://ur.430designs.com/quick-ship/#/category/

Click on a product to go to the product detail page
Any and all help is appreciated!
Leonard ZakoorSenior Front-End DeveloperAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Julian HansenCommented:
I have not looked at your code in depth and the link you provided does not seem to show products - however this is the way you would do it
function yourController(productService)
{
  var ctrl = this;
  var partNumber = 3; // Change to set current partNumber
  // Then call service like this
  ctrl.product =  productSevice.get({PartNumber : partNumber});
}

Open in new window

0
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
Hi Julian,
I do kind of have that setup already on line 68. I did modify it per your suggestion.

If you go here: https://goo.gl/HT5rTE you can see it's throwing an error. It says:
TypeError: V is not a function

Is something with my service?
0
Julian HansenCommented:
I do kind of have that setup already on line 68
Your code only goes up to line 65.
0
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

Julian HansenCommented:
This sample should demonstrate the concept
<html ng-app="app">
<body>
<div class="wrapper" ng-controller="mainCtrl as ctrl">
	<input ng-model="productId" type="text" placeholder="Product ID" />
	<button class="btn btn-sm btn-primary" ng-click="ctrl.getProduct(productId)">Load</button>
	<h2>Product Details</h2>
	<div class="row">
		<label class="col-md-2">{{ctrl.product.ProductName}}</label>
		<div class="col-md-4"><span class="text-right">{{ctrl.product.price}}</span></div>
	</div>
</div>
</body>
</html>

Open in new window

Angular
<script>
(function() {
	'use strict';
	angular.module('app',['ngResource'])
		.factory('productService', productService)
		.controller('mainCtrl', mainController);
	
	function productService($resource) 
	{
		return $resource('t2237.service.php');
	}
	
	function mainController(productService)
	{
		var ctrl = this;
		ctrl.getProduct = function(id) {
			ctrl.product = productService.get({product: id});
		};
	}
})();
</script>

Open in new window


Working sample here
0
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
Thanks for that Julian. Maybe I'm over complicating it.  I'm still getting the V is not a function error.

Here's my current code that I was referring to:
unarcoQS.controller ('prodCtrl', ['$scope', 'productService', 'ngCart', '$route', '$routeParams', '$resource', function($scope, productService, ngCart, $route, $routeParams, $resource) {
  var ctrl = this;
  id = $routeParams.PartNumber
  
  console.log(id);

  ctrl.product = productService.get({PartNumber : id});


}]); //end prodCtrl

Open in new window

0
Julian HansenCommented:
I have not figured out why yet but your parameter name PartNumber seems to be the culprit. Try changing factory to
unarcoQS.factory('productService', function ($resource) {
	return $resource('http://qsapi.unarcorack.com:7444/api/products/:PartNumber',{PartNumber: "@_PartNumber"});
});

Open in new window

And your invoke to
$scope.product = productService.query({_PartNumber: id});

Open in new window


This should get rid of the V is not a function bit but you still have a problem that a Resource GET expects a single object return and the GET in this case is returning an array - take a look at the results of this query
http://qsapi.unarcorack.com:7444/api/products/PP-CN101-UNARCOYELLOW

Open in new window

You will see it is an array of objects not a single object.
0
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
Thanks for that Julian. So is my factory wrong or my service? I didn't write the service so honestly I'm not sure why it's not doing that.

If I'm getting an array back, is there another way to show those results?
0
Julian HansenCommented:
Yes you can do a query instead of a get - the query expects an array rather than a single record.

$scope.product = productService.query({_PartNumber: id});

Open in new window


You will then also need to change your view (or controller) to either display all the records returned or (in the controller) select which one is relevant to show in the view
0
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
Hey Julian!

Thanks for that. Unfortunately I'm not getting that specific array back. Take a look here and look at the console. I'm doing
unarcoQS.controller ('prodCtrl', ['$scope', 'productService', 'ngCart', '$route', '$routeParams', '$resource', function($scope, productService, ngCart, $route, $routeParams, $resource) {
  var ctrl = this;
  id = $routeParams.PartNumber

  $scope.product = productService.query({_PartNumber: id});
  console.log($scope.product);
}]); //end prodCtrl

Open in new window



But in my console, I'm receiving about 160 records back. Is there something wrong with my controller?

I'm still new to Angular, but I do appreciate your time.
0
Julian HansenCommented:
0
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
That's what I'm seeing when I hit the API directly.

When I use my angular factory, I'm getting over 150 results. This is my first time using Angular services/factories, so I'm wondering if there's something wrong with how I've done my factory.
0
Julian HansenCommented:
Please post your factory code and your controller code together. Since you made the change to _PartNumber you only posted the controller code.

The factory is simple - it just returns a Resource.
The resource takes a URL as a parameters that optionally specifies parameters to add to the URL - you use this if the URL requires a specific format for example
my.site.com/subfolder/:ID

You can submit parameters as part of the get / query that you don't specify in the URL component - these just get sent as GET or POST parameters and can be accessed as such on the other side.

In this case the API expects the PART NUMBER to be part of the URL - so in your factory you need to tell Resource how to create that url with the _Part_Number - if you don't get that part right the URL will not include the Part Number - but it will still work and the
.query({_PartNumber: 1}) will just submit the part number data as a GET request.
0
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
Sorry about that.  Here's my entire controller.js file :
var unarcoQS = angular.module('unarcoQS',['ngResource', 'ngCart', 'ngRoute', 'angular.filter', 'ngPageTitle']);

// Factories
unarcoQS.factory('categoryService', function ($resource) {
  return $resource('http://qsapi.unarcorack.com:7444/api/products/', {});
});

unarcoQS.factory('productService', function ($resource) {
  return $resource('http://qsapi.unarcorack.com:7444/api/products/:PartNumber',{PartNumber: "@_PartNumber"});
});

unarcoQS.config(['$routeProvider', '$locationProvider',
  function($routeProvider, $locationProvider){
    $routeProvider
    .when('/',{
      data: {
        pageTitle: "Unarco Rack Quick Ship - Home"
      },
      templateUrl:'template/home.html', 
      controller: "homeCtrl"
    })
    .when('/category/',{
      data: {
        pageTitle: "Unarco Rack Quick Ship - Category"
      },
      templateUrl:'template/category.html', 
      controller: "catCtrl"
    })
    .when('/product/:PartNumber', {
      data: {
        pageTitle: "Unarco Rack Quick Ship - Product"
      },
      templateUrl: 'template/product.html',
      controller: ['$routeParams', function($routeParams) {
                      var self=this;
                      self.id = $routeParams;
                      return $routeParams;
                  }],
      controllerAs: 'prodCtrl'
    })
    .otherwise({redirectTo:'/'});

    // console.log($routeParams);
    $locationProvider.html5Mode(false);
}]);

// Controllers
unarcoQS.controller ('homeCtrl', ['$scope', 'productService', 'ngCart', '$filter', function($scope, productService, ngCart) {

}]); //end homeCtrl

unarcoQS.controller ('catCtrl', ['$scope', 'categoryService', 'ngCart', '$filter', function($scope, categoryService, ngCart) {
  ngCart.setTaxRate(7.5);
  ngCart.setShipping(2.99);

  var queryParams = {};
  categoryService.query(queryParams, {}, function (response) {
    $scope.products = response;
  });

  $scope.filtering = function(filter){
    $scope.catFilter = filter;
    // console.log(filter);
  };
}]); //end catCtrl


unarcoQS.controller ('prodCtrl', ['$scope', 'productService', 'ngCart', '$route', '$routeParams', '$resource', function($scope, productService, ngCart, $route, $routeParams, $resource) {
  var ctrl = this;
  id = $routeParams.PartNumber

  $scope.products = productService.query({_PartNumber: id}, function(product){
    $scope.product = product;
    console.log(product);
  }); 

}]); //end prodCtrl

Open in new window

0
Julian HansenCommented:
Can you look in your console for this URL
http://qsapi.unarcorack.com:7444/api/products/PP-CN101-UNARCOYELLOW

It should be a GET - expand it, click the Response tab and paste a screen shot of that.
0
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
0
Julian HansenCommented:
Not quite what I was after - you need to click the actual request in the left window (bottom) so it shows the response detail on the right
ss109.jpg
0
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
Oh, I see what you were looking for. Sorry.

So I'm receiving the the correct response. Why isn't this what's being shown in my controller?
0
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
Hey Julian,
One thing I noticed now is in the call it has a query string rather than a flat URL.

I need a call like this:
http://qsapi.unarcorack.com:7444/api/products/PP-CN101-UNARCOYELLOW

I'm getting this in the response:
http://qsapi.unarcorack.com:7444/api/products?_PartNumber=PP-CN101-UNARCOYELLOW
0
Julian HansenCommented:
Ok, I think I found your problem - I had to go to the source of the link you posted.

Look at the libraries you are including
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-resource/1.6.1/angular-resource.min.js"></script>

Open in new window


The versions don't match for angular and anagular-resource - I would change to this
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-resource/1.5.7/angular-resource.min.js"></script>

Open in new window

You should then be able to revert to your original controller / factory {PartNumber: id} and {PartNumber : "@PartNumber"} and your resource should then call the correct URL
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Leonard ZakoorSenior Front-End DeveloperAuthor Commented:
That was it! I had NO clue that ng resource and angular both had to be the same version. Thanks so much!!!
0
Julian HansenCommented:
You are welcome.
1
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Angular

From novice to tech pro — start learning today.