Avatar of Leonard Zakoor
Leonard Zakoor
 asked on

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!
AngularJavaScript

Avatar of undefined
Last Comment
Julian Hansen

8/22/2022 - Mon
Julian Hansen

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

Leonard Zakoor

ASKER
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?
Julian Hansen

I do kind of have that setup already on line 68
Your code only goes up to line 65.
Your help has saved me hundreds of hours of internet surfing.
fblack61
Julian Hansen

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
Leonard Zakoor

ASKER
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

Julian Hansen

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.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Leonard Zakoor

ASKER
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?
Julian Hansen

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
Leonard Zakoor

ASKER
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.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Julian Hansen

Leonard Zakoor

ASKER
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.
Julian Hansen

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.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Leonard Zakoor

ASKER
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

Julian Hansen

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.
Leonard Zakoor

ASKER
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
Julian Hansen

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
Leonard Zakoor

ASKER
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?
Leonard Zakoor

ASKER
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
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER CERTIFIED SOLUTION
Julian Hansen

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Leonard Zakoor

ASKER
That was it! I had NO clue that ng resource and angular both had to be the same version. Thanks so much!!!
Julian Hansen

You are welcome.