$http.post()
) are not interchangeable with the equivalent functions of Jikveri (eg, jQuery.post()
), despite that the relevant manuals describe their use in a similar way. That is, if the code in Jikvery had the following form: (function($) { jQuery.post('/endpoint', { foo: 'bar' }).success(function(response) { // ... }); })(jQuery);
var MainCtrl = function($scope, $http) { $http.post('/endpoint', { foo: 'bar' }).success(function(response) { // ... }); };
{ foo: 'bar' }
parameters from Angulyar’s request.Content-Type: x-www-form-urlencoded
and the usual string foo=bar&baz=moe
. Angulyar, however, transmits data using Content-Type: application/json
and { "foo": "bar", "baz": "moe" }
JSON strings, which, unfortunately, some server languages — especially PHP — were not originally transform into an object.x-www-form-urlencoded
for all our broadcasts. There are many solutions offered on the forums and StackOverflow, but they are not perfect, because they require either to change the server code or the $ http usage pattern. Therefore, I present to you the best possible solution that does not require any changes to the server or client code, but suggests making some minor changes to the work of $ http in the settings of the application module: // ... angular.module('MyModule', [], function($httpProvider) { // x-www-form-urlencoded Content-Type $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'; // transformRequest $http- $httpProvider.defaults.transformRequest = [function(data) { /** * ; x-www-form-urlencoded . * @param {Object} obj * @return {String} */ var param = function(obj) { var query = ''; var name, value, fullSubName, 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; }; return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data; }]; });
param()
function. Do NOT use jQuery.param()
instead; which will cause chaos when you try to use Angular’s $ resource, because jQuery.param()
will reject every $ resource class method passed to it! (This is a jQuery feature due to which the properties of the object to parameterize that contain functions are called and the value returned by them is used as a parameterized, but in the case of Angular, this can be detrimental, since we usually pass "real" instances of objects with .d.) $http.post()
and other similar methods, assuming that the existing server code is expecting x-www-form-urlencoded
data. Here are some examples of the final result for everyday, complete code (an example of what you hoped and dreamed of): <div ng-app="MyModule" ng-controller="MainCtrl"> <p ng-show="loading">Loading...</p> <p ng-hide="loading">Response: {{response}}</p> </div>
var MainCtrl = function($scope, $http) { $scope.loading = true; $http.post('/endpoint', { foo: 'bar' }).success(function(response) { $scope.response = response; $scope.loading = false; }); };
< ? header('Content-Type: application/json'); // -! $_POST ; PHP // echo json_encode($_POST); ?>
< ? $params = json_decode(file_get_contents('php://input')); // , PHP (. ) $params = json_decode(trim(file_get_contents('php://input')), true); ?>
Content-Type: application/json
, which is more logical. The article describes the approach for extreme cases when nothing can be done on the server. 'use strict'; (function() { angular.extend( angular, { toParam: toParam }); /** * , , * url * [url]http://api.jquery.com/jQuery.param/[/url] * [url]http://stackoverflow.com/questions/1714786/querystring-encoding-of-a-javascript-object/1714899#1714899[/url] * * @param object * @param [prefix] * @returns {string} */ function toParam( object, prefix ) { var stack = []; var value; var key; for( key in object ) { value = object[ key ]; key = prefix ? prefix + '[' + key + ']' : key; if ( value === null ) { value = encodeURIComponent( key ) + '='; } else if ( typeof( value ) !== 'object' ) { value = encodeURIComponent( key ) + '=' + encodeURIComponent( value ); } else { value = toParam( value, key ); } stack.push( value ); } return stack.join( '&' ); } }());
'use strict'; // change default settings var app = angular.module( 'app', [ ... ]); app .config( function( $httpProvider ) { // [url]http://habrahabr.ru/post/181009/[/url] $httpProvider.defaults.headers.post[ 'Content-Type' ] = 'application/x-www-form-urlencoded;charset=utf-8'; $httpProvider.defaults.transformRequest = function( data ) { return angular.isObject( data ) && String( data ) !== '[object File]' ? angular.toParam( data ) : data; }; });
Source: https://habr.com/ru/post/181009/
All Articles