How do I POST urlencoded form data with $http without jQuery?

How do I POST urlencoded form data with $http without jQuery?

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 the following:
method: “post”,
url: URL,
headers: {‘Content-Type’: ‘application/x-www-form-urlencoded’},
data: $.param({username: $scope.userName, password: $scope.password})

This is working, but it is using jQuery as well at $.param. For removing the 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?


Solution 1:

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.

    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}
}).then(function () {});


To use new services added with AngularJS V1.4, see

Solution 2:

URL-encoding variables using only AngularJS services

With AngularJS 1.4 and up, two services 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. $httpParamSerializerJQLike – a serializer inspired by jQuery’s .param() (recommended)

  2. $httpParamSerializer – a serializer used by Angular itself for GET requests

Example usage

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

See a more verbose Plunker demo

How are $httpParamSerializerJQLike and $httpParamSerializer different

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):

Encoding an array

{sites:['google', 'Facebook']} // Object with array property

sites[]=google&sites[]=facebook // Result with $httpParamSerializerJQLike

sites=google&sites=facebook // Result with $httpParamSerializer

Encoding an object

{address: {city: 'LA', country: 'USA'}} // Object with object property

address[city]=LA&address[country]=USA // Result with $httpParamSerializerJQLike

address={"city": "LA", country: "USA"} // Result with $httpParamSerializer

Solution 3:

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

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

Solution 4:

The problem is the JSON string format, You can use a simple URL string in data:

    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: 'username='+$scope.userName+'&password='+$scope.password
}).success(function () {});

Solution 5:

Here is the way it should be (and please no backend changes … certainly not … if your front stack does not support application/x-www-form-urlencoded, then throw it away … hopefully AngularJS does !

     method: 'POST',
     url: 'api_endpoint',
     headers: {'Content-Type': 'application/x-www-form-urlencoded'},
     data: 'username='+$scope.username+'&password='+$scope.password
 }).then(function(response) {
    // on success
 }, function(response) {
    // on error

Works like a charm with AngularJS 1.5

People, let give u some advice:

  • use promises .then(success, error) when dealing with $http, forget about .sucess and .error callbacks (as they are being deprecated)

  • From the angularjs site hereYou can no longer use the JSON_CALLBACK string as a placeholder for specifying where the callback parameter value should go.

If your data model is more complex that just a username and a password, you can still do that (as suggested above)

     method: 'POST',
     url: 'api_endpoint',
     headers: {'Content-Type': 'application/x-www-form-urlencoded'},
     data: json_formatted_data,
     transformRequest: function(data, headers) {
          return transform_json_to_urlcoded(data); // iterate over fields and chain key=value separated with &, using encodeURIComponent javascript function
}).then(function(response) {
  // on succes
}, function(response) {
  // on error

Document for the encodeURIComponent can be found here

Solution 6:

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";