Requesting Example for angular.js $http (or $resource) POST and transformRequest as a service

user2525528 picture user2525528 · Jun 26, 2013 · Viewed 18.6k times · Source

Using angular 1.1.5 and needing to pass urlencoded data to the backend. I've gotten this to work with solution from here: How can I post data as form data instead of a request payload?

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    transformRequest: function(obj) {
        var str = [];
        for(var p in obj)
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        return str.join("&");
    },
    data: xsrf
}).success(function () {});

I've embedded this into my controller with success, but the 'cleaner' way is to use a service, and $resource instead of the $http object. It is possible to use transformRequest with $resource after 1.1.2 from this topic: $resource transformResponse not working but I cannot find any working examples. Can anyone provide an example of the above solution as a service object using $resource?

Answer

Micka picture Micka · Jul 26, 2013

$RESOURCE EXAMPLE

For csrf, In a rails app you have to add <%= csrf_meta_tags %> in your header layout (if not there by default)

var app = angular.module('app', ['ngResource']);
app.config(["$httpProvider", function(provider)
{
      provider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
}]);

Here is a service object

app.factory('$folders', ['$resource', function($resource)
{
    return $resource('/folders/:id',
            { id: '@id' },
            {
              list: { method: 'GET' , isArray: true }, //same as query
              create: { method: 'POST' }, // same as save
              update: { method: 'PUT' }
              // DEFAULT IMPLEMENTATION OF $RESOURCE
              //   'get':    {method:'GET'},
              //   'save':   {method:'POST'},
              //   'query':  {method:'GET', isArray:true},
              //   'remove': {method:'DELETE'},
              //   'delete': {method:'DELETE'}
            });
}]);

Here is an example into a controller

app.controller('projectController', ['$scope', '$folders', function($scope, $folders)
{
    $scope.folders = $folders.list();
}]);

Folders.list() will automatically do GET /folders/ on the server and return the result(that should be json) as an object.

Tip:

Directly after $scope.folders = Folders.list(); in the controller, $scope.folders will be empty, it will be populated in time, when the response comes back from the server.

Simple examples with $http and $ressources http://jsfiddle.net/jhsousa/aQ4XX/

ABOUT THE FORM

here is a form

%form{'ng-submit' => 'create(item)', 'ng-controller' => 'projectController', 'ng-init' => 'item.orientation=1;'}
  %input{'ng-model'=>'item.folderName', :type => :text, :placeholder => 'Name', :name => 'folderName'}
  %textarea{'ng-model'=>'item.description', :placeholder => 'Description', :required=>true, :name => 'description'}
  %input{'ng-model'=>'item.orientation', :type=>'radio', :name=>'orientation', :value=>'1'}
  %input{'ng-model'=>'item.orientation', :type=>'radio', :name=>'orientation', :value=>'2'}
  %input{:type => :submit, :value => 'Create', :name => 'new-project'}

You'll notice the ng-model. 'ng-model'=>'item.folderName' will create a $scope.item in the projectController and add a key folderName in it. Same for the others ng-model's.

'ng-init'=>'item.orientation=1;' is going to execute the expression. So it will do the following item.orientation=1, this way we set a default value for our radio inputs, so simple.

When the form is submitted ng-submit will catch it and call the create action from the projectController with itemas parameter, no need to say that item will contain the inputs values?

Here is the controller part

app.controller('projectController', ['$scope', '$folders', function($scope, $folders)
{
    $scope.create = function(item)
    {
        f = new $folders(item);
        f.$save(function(data,headers)
                {
                   alert('SAVED');
                },
                function(err,headers)
                {
                    alert('FAILED');
                });
    };
}]);

$scope.create is the action that will be called by ng-submit, item is the item parameter from the form as well, so you'll find stuff inside such as item.description.

Folders is the service object we talked about earlier.