PHOCOA's integrated AJAX infrastructure makes adding dynamic Javascript and AJAX features to your application easy.
For any DOM event, you can configure a PHOCOA widget to:
All of this functionality uses the same PHOCOA programming model as standard form/action programming, and requires very little effort to set up.
PHOCOA also includes many YUI widgets that have AJAX capabilities, such as AutoComplete, TreeView, and PhocoaDialog (an AJAX-loading YUI Dialog) that have been plugged in nicely to PHOCOA for easy use and require even less setup. All you have to do is supply a PHP callback to provide dynamically loaded data. No Javascript code is required at all.
At the highest level, PHOCOA provides an "onEvent" property for all classes in the WFView hierarchy that is used to attach Javascript behaviors to your application. Since the onEvent interface takes in a string as a parameter, you can configure AJAX behaviors via YAML with no PHP coding. If you need more complex behavior, you can always use the PHP API, but 95% of the time you'll find that onEvent works perfectly.
The basic syntax is:
onEvent: <eventName> do <typeOfAction>[:<target>][:<action>]
JSAction
The default is the Javascript function PHOCOA.widgets.<widgetId>.events.<eventName>.handleEvent.
If you put in your own action, it will be executed as an anonymous Javascript function.
ServerAction and AjaxAction
The default is the php method <widgetId>Handle<eventName>.
If you put in your own action, it will be interpreted as the php method call of that name on the target object.
A few examples (all added to the widget of id myWidget):
Will call the Javascript function PHOCOA.widgets.myWidget.events.click.handleEvent. This is simly the "default" Javascript function based on a naming convention that phocoa will call.
Will call the Javascript function myFunc.
Will execute alert("HI").
Will refresh the page and execute the server action #page#myWidgetHandleClick (which simply calls the myWidgetHandleClick method of the page delegate).
Will refresh the page and execute the server action #page#myPhpFunc (which simply calls the myPhpFunc method of the page delegate).
Will make an AJAX request, executing the server action #module#myPhpFunc (which simply calls the myPhpFunc method of the module).
For many AJAX (a:) operations, the server will need to send data back to the client, and the client will need to react to that data.
To return data from your Ajax callback, simply return a WFActionResponse instance. There are several subclasses for handling different return types:
return new WFActionResponseJSON($phpData);
return new WFActionResponseJSON($xmlString);
return new WFActionResponsePlain($textString);
return WFActionResponsePhocoaUIUpdater::WFActionResponsePhocoaUIUpdater()->
->addUpdateHTML('myDiv', '<b>new html</b>')
->addReplaceHTML('myOtherDiv',
'<div id="myOtherDiv">replacement div</div>')
->addRunScript('alert("You did it!");');
When your Ajax call completes successfully, the clickSuccess handler for that widget (if it exists) will be executed.
Example:
// php handler
public function myCustomFunction($page, $params, $senderId, $eventName) {
// do stuff
return new WFActionResponseJSON(array('customString' => 'something meaningful'));
}
// javascript handler
PHOCOA.namespace('widgets.myLink.events.click');
PHOCOA.widgets.myLink.events.click.ajaxSuccess = function(response) {
// response is a native Javascript object
alert(response.CustomString);
}
PHOCOA uses a delegation paradigm to implement the AJAX integration. We have already looked at the default handleEvent delegate method above. There are a few additional delegate methods that you can implement if you want to pass arguments to your handleEvent function, or have specialized success or error handlers.
The setup for this is done in the YAML file by specifying the onEvent property:
And, in Javascript, set up the delegate functions:onEvent: click do j
PHOCOA.namespace('widgets.localAction.events.click');
PHOCOA.widgets.localAction.events.click.collectArguments = function() { return ['myArg1', 'myArg2']; };
PHOCOA.widgets.localAction.events.click.handleEvent = function(e, myArg1, myArg2) {
alert("I've been clicked!\nThe first argument to the callback is the event: "
+ e + "\nFollowed by all arguments from collectArguments(): " + myArg1 + ", " + myArg2);
};
ServerAction The server will stick a random number in this space when you click the link above.
The setup for this is also trivially simple. In the YAML file:
In PHP, we implement the default callback method <widgetId>Handle<EventName>:onEvent: click do s
function rpcPageDelegateServerHandleClick($page, $params, $senderId, $eventName)
{
if (WFRequestController::sharedRequestController()->isAjax())
{
return WFActionResponsePhocoaUIUpdater::WFActionResponsePhocoaUIUpdater()
->addUpdateHTML('ajaxTarget', 'I am the server and this is my random number: ' . rand());
}
else
{
$page->outlet('ajaxTarget')->setValue('I am the server and this is my random number: ' . rand());
}
}
You will notice that we handle the event different based on whether the call is an AJAX call or not...
For the ServerAction, we need only update the widget's value. This will be reflected in the HTML response that is sent to the client, just as done in normal PHOCOA action handlers.
For the AjaxAction, to effect the UI updates on the client, we return a WFActionResponsePhocoaUIUpdater object. This object has addUpdateHTML(), addReplaceHTML(), and addRunScript() methods that make it easy for you to update the innerHTML of any element, replace any element, and run Javascript code in response to an AjaxAction.
We are using the same example as above, but turning it into an AJAX action.
AjaxAction Click the link and look to the right of the "ServerAction" link above...
For this example, we want to call a PHP method other than the default, since we've already set up the method we need for the above example:
onEvent: click do a:rpcPageDelegateServerHandleClick
The PHOCOA Ajax integration supports several DOM events, which are allowed on most of the WFView subclasses. The blocks below demonstrate various UI widgets and DOM events:
The PHOCOA programming model for form submission is extended with our Ajax integration. Everything works the same way, except that you can return WFActionResponse objects to effect UI changes from the server. Even PHOCOA's validation infrastructure works with Ajax.
Below is an example form with two fields. The first field requires any string but "bad" and the second field requires any string but "worse". If there are no errors, the two strings will be interpolated into a single response and updated in the UI.
The submit button is a normal form submit. The link will submit the form via Ajax.
Once again, the code to build this Ajax functionality is quite simple.
In YAML, we set up our link to trigger the form submission:
We also implement our ajaxFormSubmitNormal action handler, which in this example, we use for both normal and ajax form submission:onEvent: click do a:ajaxFormSubmitNormal
function ajaxFormSubmitNormal($page, $params, $senderId, $eventName)
{
$result = 'You said: "' . $page->outlet('textField')->value() . '" and "' . $page->outlet('textField2')->value() . '".';
if (WFRequestController::sharedRequestController()->isAjax())
{
return WFActionResponsePhocoaUIUpdater::WFActionResponsePhocoaUIUpdater()
->addUpdateHTML('ajaxFormResult', $result);
}
else
{
$page->assign('formResult', $result);
}
}
When combined with the template code:
<div id="ajaxFormResult">{$formResult}</div>
The proper result is displayed either by Ajax or by traditional template programming.
In Javascript, we have an eventHandler to "remove" our "result" when the request is submitted. This prevents previous results from showing if there is an error with the current submission.
PHOCOA.namespace('widgets.ajaxFormSubmitAjax.events.click');
PHOCOA.widgets.ajaxFormSubmitAjax.events.click.handleEvent = function(e) {
$('ajaxFormResult').update();
};