Default $resource POST data

All we need is an easy explanation of the problem, so here it is.

That might be strange but I need to specify some default POST data for my $resource using the factory method of the module.

Does anyone have an idea of how to do that in AngularJS ?

EDIT :

Well, i want to do something like this :

/**
 * Module declaration.
 * @type {Object}
 */
var services = angular.module("services", ["ngResource"]);

/**
 * Product handler service
 */
services.factory("Product", function($resource) {
    return $resource("http://someUrl", {}, {
        get   : {method: "GET", params: {productId: "-1"}},
        update: {method : "POST", params:{}, data: {someDataKey: someDataValue}}
    });
});

Where data is the default data for my future POST requests.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

This is not really the angular way to do such a thing as you lose data consistency if you do it and it doesn’t reflect in your model.

Why?

The resource factory creates the object and uses object instance data as POST. I have looked at the documentation and angular-resource.js and there doesn’t seem to be a way to specify any default custom properties for the object being created by resource without modifying angular-resource.js.

What you can do is:

services.factory("Product", function($resource) {
    return $resource("http://someUrl", {}, {
        get   : {method: "GET", params: {productId: "-1"}},
        update: {method : "POST"}
    });
});

and in your controller:

$scope.product = {}; // your product data initialization stuff
$scope.product.someDataKey = 'someDataValue'; // add your default data

var product = new Product($scope.product);
product.$update();

Method 2

I think it will depend on how you call the update function. If you read the angular main page’s tutorial, under “Wire up a Backend”, the mongolab.js provides a ‘Project’ factory. Copied verbatim:

angular.module('mongolab', ['ngResource']).
factory('Project', function($resource) {
  var Project = $resource('https://api.mongolab.com/api/1/databases' +
      '/angularjs/collections/projects/:id',
      { apiKey: '4f847ad3e4b08a2eed5f3b54' }, {
        update: { method: 'PUT' }
      }
  );

  Project.prototype.update = function(cb) {
    return Project.update({id: this._id.$oid},
        angular.extend({}, this, {_id:undefined}), cb);
  };

  Project.prototype.destroy = function(cb) {
    return Project.remove({id: this._id.$oid}, cb);
  };

  return Project;
});

The usage is that you first get an instance of the Project:

project = Project.get({id:1});

Then do an update after some changes:

project.update(someFunction);

In your case, you can change the update to always add the data you need:

Product.prototype.update = function(cb) {
  return Product.update({},
      angular.extend({}, this, {someDataKey: someDataValue}), cb);
};

Otherwise, you can most likely put the key/value pair in the params:

    update: {method : "POST", params:{someDataKey: someDataValue}}

It will be POSTed with the key/value pair in the URL, but most app servers nowadays will throw the pair into the params object anyway.

Method 3

I think most have missed a tiny gem in the documentation here.

non-GET "class" actions: Resource.action([parameters], postData, [success], [error])

This suggests you can do the following.

var User = $resource('/user');
postData = { name : 'Sunil', 'surname' : 'Shantha' };

var user = User.save({notify:'true'}, postData, function() {
  // success!
});

The second parameter when doing a save action (post) is post data.

Method 4

Wrapper function will work.

function myPost(data) {
  return $http.post('http://google.com', angular.extend({default: 'value'}, data))
}

myPost().success(function(response) { ... });

Method 5

Might this solve your problem?

services.factory("Product", function($resource) {
  return $resource("http://someUrl", {}, {
    get   : {method: "GET", params: {productId: "-1"}},
    update: {method : "POST", params:{}, data: {someDataKey: someDataValue}}
  });
});
services.factory("DefaultProduct", function(Product) {
  return function(){
     return new Product({
        data:"default";
     });
  };
});
services.controller("ProductCTRL",function($scope,DefaultProduct){
  $scope.product = new DefaultProduct();
});

Method 6

You can just merge your params with the default. Everything not available in params will be provided by the default object. Everything available will be overwritten by myParams

services.factory("Product", function($resource) {
    return $resource("http://someUrl", {}, {
        get   : {method: "GET", params: {productId: "-1"}},
        update: {method : "POST", params:angular.extend(myDefault, myParams);}
    });
});

where myParams would be your list of variables and myDefault your default values as a json object.

Method 7

You can set default fields on your request by using transformRequest option for your $resource‘s actions that use the POST method.

For example something like this

function prependTransform(defaults, transform) {

 // We can't guarantee that the default transformation is an array
 defaults = angular.isArray(defaults) ? defaults : [defaults];

 // Append the new transformation to the defaults
 return [transform].concat(defaults);
}

ctrl.factory('MyResource', ['$resource', '$http',
function($resource, $http) {
    return $resource('/path/to/myresource/:id', {id : '@id'},
           { 
               create : {
                   method : 'POST',
                   transformRequest : prependTransform($http.defaults.transformRequest,
                      function(data, headers) {
                           return addDefaultField(data);
                      }
                  ),
               },
           });
    }
]);

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply