2

I'm trying to create an object in Angular.

Here is my factory

angular.module('myApp')
    .factory('Order', function($resource) {
        return $resource('/api/products?id=:id/orders?id=:orderId', { id: "@_id" }, {
            query: { method: 'GET', isArray: false },
            update: { method: 'PUT'}
        });
    });

Here is my controller

angular.module('myApp').controller('OrderCtrl',
  function ($scope, $rootScope, $stateParams, Order, Auth) {
    $scope.myOrder = Order.get({"id": 1, "orderId": 1});
  }
});

Here is my routes.js file in my server directory

app.use('/api/products', require('./api/product'));

In my api/products directory, I have an index file

var express = require('express');
var controller = require('./product.controller');

var router = express.Router();
// Endpoints for products
router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.create);
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
router.delete('/:id', controller.destroy);

// Endpoints for product - order definitions
router.get('/:id/orderDefinitions', controller.showOrderDefinitions);
router.post('/:id/orderDefinitions', controller.addOrderDefinitions);

// Endpoints for product - orders
router.get('/:id/orders', controller.showProductOrders);
router.get('/:id/orders/:orderId', controller.showIndividualProductOrder);
router.put('/:id/orders/:orderId', controller.updateIndividualProductOrder);
router.delete('/:id/orders/:orderId', controller.deleteOrder);

module.exports = router;

Here are the two endpoints I'm trying to access

router.get('/:id/orders/:orderId', controller.showIndividualProductOrder);
router.put('/:id/orders/:orderId', controller.updateIndividualProductOrder);

Here is my controller

exports.showIndividualProductOrder = function(req, res) {
  Product.findById(req.params.id, function (err, product) {
    if(err) { return handleError(res, err); }
    if(!product) { return res.send(404); }
    Order.find({productId: product._id, _id: req.params.orderId}, function (err, order) {
      console.log("found individual product order", order);
      if(err) { return handleError(res, err); }
      if(!order) { return res.send(404); }
      // Get product's order
      return res.json(order[0]);
    });

  });
};

// Update an individual order for a product
exports.updateIndividualProductOrder = function(req, res) {
  Order.find({productId: product._id, _id: req.params.orderId}, function (err, order) {
    if(err) { return handleError(res, err); }
    if(!order) { return res.send(404); }

    var updatedOrder = _.merge(order, req.body);
    console.log("updating order", order, updatedOrder);
    updatedOrder.save(function (err) {
      if (err) { return handleError(res, err); }
      return res.json(200, product);
    });

  });
};

And yet, I still get this error

Error: [$resource:badcfg] Error in resource configuration for action get. Expected response to contain an object but got an array (Request: GET /api/products?id=1/orders?id=1)

I used Postman to test the API endpoints, and the JSON output is an array. But in my factory, I clearly stated that I didn't want an array with the isArray option.

Richard Hamilton
  • 25,478
  • 10
  • 60
  • 87
  • `get` and `query` are different methods in $resource. You specified `isArray` on `query` but not `get`. Also setting to false suggests will be object. End result you still have a mismatch of object types. Simplest might be make `isArray:true` on query and use that method instead of get – charlietfl Jul 17 '15 at 21:34

1 Answers1

2

I used Postman to test the API endpoints, and the JSON output is an array. But in my factory, I clearly stated that I didn't want an array with the isArray option.

With the isArray flag you don't specify what you want, you specify what is to be expected on that particular API endpoint.

If you don't want an array, change the backend code, but if it is an array, then use isArray: true in the configuration.

Edit: you can use the tranformResponse property to specify a converter function for the data, which would enable you to use an endpoint returning an object, but still use a resource method configured for an array with isArray:true (and vice versa), see this answer for an example.

Community
  • 1
  • 1
doldt
  • 4,466
  • 3
  • 21
  • 36