AngularJS $http service with WordPress

Some time ago I needed to create a branch of feature rich WordPress plugins for client’s specific needs.  I like AngularJS for its structured and concise nature, decided to use it in these projects.  I’ve written a part of client side logic then I realized that I can’t trigger wp_ajax_ hooks via Angular’s $http service as with jQuery ajax methods.

Googling has brought to me a cool solution. https://habrahabr.ru/post/181009/

The root of a problem is Angular’s $http service  sends data as application/json  but WordPress expects data to be sent as x-www-form-urlencoded  just as you’ll submit ordinal  html form.  Wordpress sets up it’s ajax hooks to actions and you have to specify action name as action parameter of POST request.

The idea is to modify  Angular’s $http service behavior to act just like jQuery ajax methods. And it works perfectly.

So you may ask why I wrote about it again, if there is a solution already?  🙂

It’s because original solution doesn’t take into account Date type, if you pass data to this toParam function which will urlencode them just as you’d send them as html form  and this data object will contain  js Date object  it will not send correct information to server, it will try recursively parse date object instead, and it makes no sense.  As a result you can’t send data containing Date objects correctly.

This snippet is a solution for overall problem, with fix due to Date objects.

Hope it’ll help somebody. That’s why I posted it.

You can copy and save it as is and just add this file to your js bundle, the only thing you need to do is to change YourAppModuleNameHere at line to your main AngularJS app module name.

/**
* Created by Mikhail.root on 22.02.2016. originaly from http://habrahabr.ru/post/181009/
* Fixed encoding of JS Date objects
*/
(function () {
'use strict';
angular.extend(angular, {toParam: toParam})
.module('YourAppModuleNameHere') // set it to your app module name!
.config(['$httpProvider',function ($httpProvider) {
$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;
};
}
]);
/**
* Преобразует объект, массив или массив объектов в строку,
* которая соответствует формату передачи данных через 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 if (value instanceof Date) {
value = encodeURIComponent(key) + '=' + encodeURIComponent(value.toISOString());
} else {
value = toParam(value, key);
}
stack.push(value);
}
return stack.join('&');
}
})();

view raw
toParam.js
hosted with ❤ by GitHub

Happy codding!

Leave a Reply

Your email address will not be published. Required fields are marked *