How do I POST urlencoded form data with $http in AngularJS?

I am new to angularJS, and for a start, I thought to develop a new application using only AngularJS.

I am trying to make an AJAX call to the server side, using $http from my Angular App.

For sending the parameters, I tried following:

$http({
    method: "post",
    url: URL,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: $.param({username: $scope.userName, password: $scope.password})
}).success(function(result){
    console.log(result);
});

This is working but, it is using jQuery as well near, $.param. For removing dependency on jQuery, I tried,

data: {username: $scope.userName, password: $scope.password}

But this seemed to fail. Then I tried params:

params: {username: $scope.userName, password: $scope.password}

But this also seemed to fail. Then I tried JSON.stringify:

data: JSON.stringify({username: $scope.userName, password: $scope.password})

I found these possible answers to my quest, but was unsuccessful. Am I doing something wrong.? I am sure, AngularJS would provide this functionality. But how.?

I think you need to do is to transform your data from object not to JSON string, but to url params.

From Ben Nadel's blog.

By default, the $http service will transform the outgoing request by serializing the data as JSON and then posting it with the content- type, "application/json". When we want to post the value as a FORM post, we need to change the serialization algorithm and post the data with the content-type, "application/x-www-form-urlencoded".

Example from here.

$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: {username: $scope.userName, password: $scope.password}
}).success(function () {});

AngularJS 1.4.x allows urlencoding objects without dependencies or transformRequest

AngularJS 1.4.x introduced two new services that can handle the process of url-encoding data for POST requests, eliminating the need to manipulate the data with transformRequest or using external dependencies like jQuery:

  1. $httpParamSerializer which is from now on also the default serializer for GET parameters in the $http service

  2. $httpParamSerializerJQLike an alternative serializer inspired by jQuery's .param()

Example usage

$http.post({
  url: 'some/api/endpoint',
  method: 'POST',
  data: $httpParamSerializerJQLike($scope.appForm.data), // Make sure to inject the service
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded' // Note the appropriate header
  }
}).success(function(response) { /* do something here */ });

See a more verbose Plunker demo


About the difference between $httpParamSerializer and $httpParamSerializerJQLike

In general, it seems $httpParamSerializer uses less "traditional" url-encoding format than $httpParamSerializerJQLike when it comes to complex data structures.

For example (ignoring percent encoding of brackets):

  • With an array property of a data object such as {sites:['google', 'Facebook']}
    • $httpParamSerializer would return sites=google&sites=facebook
    • $httpParamSerializerJQLike would return sites[]=google&sites[]=facebook
  • With an object property of a data object such as {address: {city: 'LA', country: 'USA'}}
    • $httpParamSerializer would return address={"city": "LA", country: "USA"}
    • $httpParamSerializerJQLike would return address[city]=LA&address[country]=USA

All of these look like overkill (or don't work)... just do this:

$http.post(loginUrl, "userName=" + encodeURIComponent(email) +
                     "&password=" + encodeURIComponent(password) +
                     "&grant_type=password"
).success(function (data) {

From the $http docs this should work..

  $http.post(url, data,{headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
    .success(function(response) {
         // your code...
     });

If it is a form try changing the header to:

headers[ "Content-type" ] = "application/x-www-form-urlencoded; charset=utf-8";

and if it is not a form and a simple json then try this header:

headers[ "Content-type" ] = "application/json";

This worked for me. I use angular for front-end and laravel php for back-end. In my project, angular web sends json data to laravel back-end.

This is my angular controller.

var angularJsApp= angular.module('angularJsApp',[]);
angularJsApp.controller('MainCtrl', function ($scope ,$http) {

    $scope.userName ="Victoria";
    $scope.password ="password"


       $http({
            method :'POST',
            url:'http://api.mywebsite.com.localhost/httpTest?callback=JSON_CALLBACK',
            data: { username :  $scope.userName , password: $scope.password},
            headers: {'Content-Type': 'application/json'}
        }).success(function (data, status, headers, config) {
            console.log('status',status);
            console.log('data',status);
            console.log('headers',status);
        });

});

This is my php back-end laravel controller.

public function httpTest(){
        if (Input::has('username')) {
            $user =Input::all();
            return  Response::json($user)->setCallback(Input::get('callback'));
        }
    }

This is my laravel routing

Route::post('httpTest','HttpTestController@httpTest');

The result in browser is

status 200
data JSON_CALLBACK({"username":"Victoria","password":"password","callback":"JSON_CALLBACK"}); httpTesting.js:18 headers function (c){a||(a=sc(b));return c?a[K(c)]||null:a}

There is chrome extension called postman. You can use to test your back-end url whether it is working or not. https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en

hopefully, my answer will help you.

you need to post plain javascript object, nothing else

           var request = $http({
                method: "post",
                url: "process.cfm",
                transformRequest: transformRequestAsFormPost,
                data: { id: 4, name: "Kim" }
            });

            request.success(
                function( data ) {
                    $scope.localData = data;
                }
            );

if you have php as back-end then you will need to do some more modification.. checkout this link for fixing php server side