2

I want to nest the parameters sent to the backend server. So far my current resource looks like

  angular
    .module('myApp.users')
    .factory('User', user);

  user.$inject = ['$resource'];

  function user($resource) {
    return $resource('/users.json');
  }

In my controller...

var user = new User({name: 'jason', email: 'jason@gmail.com'});
user.$save()

The params sent to my backend server end up looking like

{name: 'jason', email: 'jason@gmail.com'}

Ideally, I want the params sent to the backend server to look like

 {user: {name: 'jason', email: 'jason@gmail.com'}}

I know that in the controller I can write

var user = new User({user: {name: 'jason', email: 'jason@gmail.com'}});

However, I don't like that approach. What I want to know is, is there a way to create nested parameters in the User resource and not in the controller. Can the paramsDefault argument help here?

thank_you
  • 11,001
  • 19
  • 101
  • 185
  • You should check [this](http://stackoverflow.com/questions/34744611/angularjs-transform-data-before-send-with-ng-resource-and-transformrequest) post. Try to use transform request. And [here](https://docs.angularjs.org/api/ng/service/$http) is the official docs for that – Michael Jan 23 '17 at 13:38
  • I'll look into this. That said, I really enjoy the brevity I have with the $resource object: `return $resource('/users.json');`. If I can prevent myself from having to manually create different resource actions such as update and create, my work would be stellar. – thank_you Jan 23 '17 at 14:03
  • How about using a service? Have you considered it? – Everton Santos Jan 23 '17 at 15:54
  • Maybe this can help http://www.nesterovsky-bros.com/weblog/2015/05/07/InterceptAngularjsResourceRequest.aspx – Vaibhav Bansal Jan 23 '17 at 16:04
  • @EvertonSantos I've thought about it. That said, it adds complexity to my code. I would almost rather just tolerate the problem then build a service to solve it. – thank_you Jan 23 '17 at 16:39
  • @VaibhavBansal Although that may help, there must be another way to add options to my resource object without custom building the actions. – thank_you Jan 23 '17 at 16:41

3 Answers3

0

According to the official documentation, you should be able to wrap/map input data using the transformRequest property: https://docs.angularjs.org/api/ngResource/service/$resource

Try following code:

function user($resource) {
  var actions = {
    transformRequest: function(data, headersGetter){
      return {
        user: data
      }
    }
  }
  return $resource('/users.json',{},actions)
}

See as well this question and answers explaining similar solution: Angularjs: Transform data before send with ng-resource and transformRequest

Community
  • 1
  • 1
rscheibinger
  • 161
  • 1
  • 3
  • My interpretation of the docs tells me that I can apply transformReques only to specific actions. For example, in the SO question you provided they had transformRequest INSIDE the update action. That's exactly what I'm trying to avoid. – thank_you Jan 25 '17 at 18:44
0

You may add a prototype method to User constructor function

app.factory('User', function ($resource) {
        var User = $resource('/users.json');

        // add custom method below 
        User.prototype.getSpecificUser = function() {
            return new User({user: {name: 'jason', email: 'jason@gmail.com'}});
        };
        return User;
    });

In your Controller

User.getSpecificUser()
0

What do you think about writing a simple wrapper for $resource ? I have set up an example plnkr:

The idea is to pass desired namespace to the wrapper and then just extend each action with transformRequest function:

app.factory('myResource', function($resource) {
  return function(namespace, url, paramDefaults, actions, options) {
    var transformRequest = function(data) {
      var payload = {};
      payload[namespace] = data;
      console.log(payload);
      return data;
    }

    // ngResource default actions: https://github.com/angular/angular.js/blob/master/src/ngResource/resource.js#L510
    actions = actions || {
      'get': {method: 'GET'},
      'save': {method: 'POST'},
      'query': {method: 'GET', isArray: true},
      'remove': {method: 'DELETE'},
      'delete': {method: 'DELETE'}
    };
    Object.keys(actions).map(function(action){
      actions[action].transformRequest = transformRequest;
    });

    return $resource(url, paramDefaults, actions, options)
  };
});

Then an actual factory would look like:

angular
  .module('myApp.users')
  .factory('User', user);

  user.$inject = ['myResource'];

  function user(myResource) {
    return myResource('user', '/users.json');
  }
Slava.K
  • 3,073
  • 3
  • 17
  • 28