From Steven de Klerk, Senior Developer at
BlueBox:
New Ajax functionality has been added to
BB2 this week, allowing
for any PHP function to be easily accessed via JavaScript through the
use of Ajax and optional JSON objects, without the need for additional
coding. The function to call via Ajax is simply called "ajax" and is
available on all BB2 modules. This function accepts a few parameters,
listed below:
- global[ajax_method] - Required. Sets the function to be called within the module
- global[param]
- Optional. The parameters to be passed to the called function, as an
indexed array. So, param[0], would be the first parameter. param[1] the
second, and so on. e.g. $_class->method(param[0], param[1]);
- global[json_encode] - Optional. Sets the response to the Ajax call.
Default is a basic "success" response, otherwise when this param is set
to "1", it will return a JSON encoded object.
The new "ajax" function does a permission check to ensure
the user can run the "ajax_method" listed, and then either returns a
basic "success" if the function was run without problems, or returns a
JSON object, which would be the primary use for this new functionality.
Let's say we wanted to add a new user with the user
name of "testuser" and the first name of "Paul". To do this, we'd simply
call the following url:
/?class=bb_users&method=ajax&global[ajax_method]=add&global[param][0][this_class]=bb_users&global[param][0][fields][name]=testuser&global[param][0][fields][first_name]=Paul
Breaking that up, you'll see we've called "ajax" on the
class "bb_users", and set the PHP function as "add". We then pass
through the parameters. Since the "add" function only takes one mixed
array, we're going to set global[param][0] with our array of data. In
this case, it's just the "this_class" parameter, and then the "name" and
"first_name" fields. Since we haven't set it to return a JSON encoded
object, it will just print out the text "success" on completing. If you
use this method, make sure to check that the response text only contains
the word "success" (responseText == 'success'), as an error could also
be present, and should be displayed to the user in that case.
This, however, doesn't fully utilize the new
functionality. To do this, "global[json_encode]=1" should be passed in
the url, telling the ajax function to return a usable JSON object, which
provides far more information. For example, running the same url above,
but with the included JSON encoding switch, we see the returned data
is:
{"response":{"this_class":"bb_users","fields":{"name":"testuser","first_name":"Paul"},"do_not_redirect":"true","_id":"52"},"rows":4,"html":"","status":"success","error":""}
This is a JSON encoded string, and thanks to JavaScript
libraries such as Prototype, we can turn this into an easy to use
object by calling "evalJSON()" on the reponseText. The JSON object
contains a few parameters:
- response - the response from the function called. This can be anything, depending on what the function returns
- rows - the number of rows. If there's only 1 result (such as a "get" or "add" call), it will list the number of elements.
- html - any outputted HTML while running the function. Useful if the function does resp/print calls
- status - whether the function completed successfully or not
- error - any errors that may have been caught while running the function
The first thing to do when checking the response, is to
make sure that the "status" parameter == 'success', and if it doesn't,
then check the "error" parameter to see if any errors were caught. If it
was successful, you can now check the function response and use the
returned data. So, if we wanted to alert the new _id of the user we
added, we can do so like this (assuming that the variable "data" is the
evaluated JSON object):
if (data.status == 'success') {
alert(data.response._id);
} else {
alert('Error: ' + data.error);
}
Handling
and calling the new "ajax" function can all be done fairly easily
through Prototype's Ajax.Request functionality, however, to make things
even easier, there's a new BB2 ajax function which handles most of the
leg work described above.
The new JavaScript function is called "ajax2json", and is a quick and easy gateway to the above functionality.
The new function takes the following parameters:
ajax2json(callback, className, method, param, loaderElm, largeLoader)
- callback - Required. (function) The callback function when the response has arrived from the request
- className - Required. (string) The BB2 class/module to call
- method - Required. (string) The BB2 method to call on the above class
- param - Optional. (object) An object containing the parameters to be passed to the above class->method
- loaderElm - Optional. (string) The HTML element to add a loading spinner during the request
- largeLoader - Optional. (bool) Whether or not to use a large spinner
So,
let's do the same user add as above, and then get a list of users with
the same name as what we've added. To start off with, we'll create a
callback handler and then an "add" function:
function handleAddResponse(data) {
if (data.status == 'success') {
alert('New record added with _id: ' + data.response._id);
} else {
alert('Error: ' + data.error);
}
}
function addUser() {
var param = {
0: {
fields: {
name: 'testuser',
first_name: 'Paul'
}
}
};
ajax2json(handleAddResponse, 'bb_users', 'add', param);
}
Breaking down the above, we call "ajax2json"
with the callback function "handleAddResponse", which checks to make
sure the response was successful, and if so, it alerts the new _id. We
then set the class, method and parameters which is a basic JavaScript
object, made up of the fields we want to set.
Once we've added our user, we want to get a list of
users with the name "Paul" and then handle that data. This can be done
like so:
function handleListResponse(data) {
if (data.status == 'success') {
alert('Found ' + data.rows + ' row(s).');
data.response.each(function (row) {
var output = '';
for (var field in row) {
output += field + ': ' + row[field] + '\n';
}
alert(output);
});
} else {
alert('Error: ' + data.error);
}
}
function listUsers() {
var param = {
0: {
where: 'first_name LIKE \'%paul%\''
}
};
ajax2json(handleListResponse, 'bb_users', 'getList', param);
}
This
time our callback function is a bit more advanced, as we're going to
run through the response data and alert the values. If we do the add
before the list, we'll get back at least one row containing all of the
data for our new user record. We can now display this data in a table,
use it in another add, and more.
With this new functionality, there should no longer be a
need to create additional BB2 functions to act as "proxies" between
standard and custom BB2 functions and the browser, as we can now pass
and receive data between the PHP side of BB2 and the client/browser side
seamlessly.