Make NG’s $HTTP service as easy to use as jquerr. Ajax()

Time:2019-12-8

Author Zeke
Many beginners of NG have such a puzzle: why the $HTTP service, such as $http. Post(), is similar to jQuery’s $. Post(), but can’t be replaced directly, for example:

(function($) {
  jQuery.post('/endpoint', { foo: 'bar' }).success(function(response) {
    // ...
  });
})(jQuery);

Such code does not work properly in ng.

var MainCtrl = function($scope, $http) {
  $http.post('/endpoint', { foo: 'bar' }).success(function(response) {
    // ...
  });
};

You will find that your server did not receive the parameter {foo: ‘bar’}

The difference is whether jQuery and ng serialize data when they transfer it. The root cause is that your server is unable to interpret the raw data delivered by ng. By default, JQ uses content type: x-www-form-urlencoded to transcode data to foo = Bar & Baz = MOE. Ng is content type: application / JSON to send the JSON string of {“foo”: “bar”, “Baz”: “MOE”}, which makes the server (especially PHP) unable to interpret such data.

Fortunately, the thoughtful ng developers have provided $HTTP hooks so that we can force x-www-form-urlencoded to send data. Many people have provided solutions for this, but they are not ideal because you have to modify your server code or $HTTP code. In this case, I give the best possible solution, and the code at the front and back end does not need to be modified:

// Your app's root module...
angular.module('MyModule', [], function($httpProvider) {
  // Use x-www-form-urlencoded Content-Type
  $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
 
  /**
   * The workhorse; converts an object to x-www-form-urlencoded serialization.
   * @param {Object} obj
   * @return {String}
   */
  var param = function(obj) {
    var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
      
    for(name in obj) {
      value = obj[name];
        
      if(value instanceof Array) {
        for(i=0; i<value.length; ++i) {
          subValue = value[i];
          fullSubName = name + '[' + i + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value instanceof Object) {
        for(subName in value) {
          subValue = value[subName];
          fullSubName = name + '[' + subName + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value !== undefined && value !== null)
        query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
    }
      
    return query.length ? query.substr(0, query.length - 1) : query;
  };
 
  // Override $http service's default transformRequest
  $httpProvider.defaults.transformRequest = [function(data) {
    return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
  }];
});

Do not use jQuery. Param() instead of the param() method above, which will make NG’s $resource method unusable.

Recommended Today

ASP.NET Example of core MVC getting the parameters of the request

preface An HTTP request is a standard IO operation. The request is I, which is the input; the responsive o is the output. Any web development framework is actually doing these two things Accept the request and parse to get the parameters Render according to the parameters and output the response content So let’s learn […]