1

I want to change some data before sending it to the server via ng-resource. I use the tranformRequest-Function like this:

    update: {
        method: 'PUT',
        transformRequest: function (data) {
             // modify data then
             return data;
        }
    }

I can modify data this way but in the request my data is always serialized. I want keep my data as JSON. Is this possible with transformRequest or have this to be done in controller. I would prefer to do it in the service. Thx for help

4 Answers 4

7

Omg i feel like an idiot. You simply have to do

update: {
    method: 'PUT',
    transformRequest: function (data) {
         // modify data then
         return angular.toJson(data);
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Carefull this won't work in all case, if you check the implementation my defaultToJson (which is from angular-resource) you see that it use some condition before usung that angular.toJson). So it may work for you but it won't work for all this is why i have a more complicated answer.
Ok, i will consider this. Ty
4

Here's an example I'm using in my app. Callers of the $resource methods pass in a simple list of parameters as JSON, and the transformRequest bundles the parameters into the format expected by the API I'm using.

var myServices = angular.module('myServices', ['ngResource']);
...
myServices.factory('MyServer', ['$resource', function($resource){
    var formatLoginRequest = function(data) {
        // input looks like: {username:"imauser", pw:"password"}
        // output should be: {request: {cmd:"login", username:"imauser", pw:"password"}}
        data.cmd="login";
        data = {request: data};
        data = angular.toJson(data);
        return data;
    };
    ...
    return = $resource('https://api.server.com/', {}, {
        login: {method:'POST', params:{}, isArray:false, transformRequest:formatLoginRequest },
        ...other methods defined here...
});

As noted elsewhere, angular.toJson() won't correctly serialize all data types, but it is sufficient for my case with JSON.

Comments

2

In case somebody else comes across this, Angular provides default transformations for objects. The $http service exposes defaults.transformRequest, which checks if the data property is an object and automatically serializes it to JSON.

For this particular case, i would do a simple check if data is an object and if not make it one and override the $http.defaults.transformRequest.

function appendTransform(defaults, transform) {
  defaults = angular.isArray(defaults) ? defaults : [defaults];
  return defaults.concat(transform);
};

update: {
    method: 'PUT',
    transformRequest: 
 appendTransform($http.defaults.transformResponse,function(data) {
      data = angular.isObject(data) ? data : {data};
      return data;
     })
}

Comments

0

Yes it is. A bit troublesome and ulgy but here it is :

// from angular-resource
var toString= function() {
    var value = [];
    _.forEach(this, function(e) {
            value.push('' + e);
            });
        return '[' + value.join(', ') + ']';
      };
      var isObject = function isObject(value) {
          // http://jsperf.com/isobject4
          return value !== null && typeof value === 'object';
        };
    var isFile = function(obj) {
      return toString.call(obj) === '[object File]';
    }


    var isFormData = function(obj) {
      return toString.call(obj) === '[object FormData]';
    }


    var isBlob = function(obj) {
      return toString.call(obj) === '[object Blob]';
    }
    var defaultToJson = function(d) {
          return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? angular.toJson(d) : d;
    };
    this.typeServiceProcessData = function(d){
             //[put your code here for to change data this will be called before angular default serialization to the server]
    };
    this.typeServiceProcessJsData = function(d){
        //[for data that come back from the server after getting parse by default angular json parsing]
    };


// sample creation of a resource method, be really carefull about the order in transformResponse and transformRequest

'get': {method:'GET', transformResponse:[$http.defaults.transformResponse[0], this.typeServiceProcessData]},

'create':   {method:'POST', url:baseResourceUrl, transformRequest:[this.typeServiceProcessJsData, defaultToJson]},

It's a big huge, it's a code i done some time ago and i copy/pasted some function definition from angular-resource because they weren't define in that scope and weren't accessible from outside of angular resource. To see why they're needed check the defaultToJson function i defined which is the angular default.

If someone has a better way to just copy paste that bunch of function i take too :)

1 Comment

ty i will give it a try

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.