Introduction
If you have been following the Zend Framework at all, you’ll know that Dojo has been selected as the UI library to be adopted into the Zend Framework. The question is what does this exactly mean? I’m still trying to figure out how they are going to use dojo, but right now with release 1.6 you can create dojo widgets (e.g. – date pickers, currency boxes, specialized buttons etc…) in code with the Zend_Dojo object. That being said, you still need to learn a few more things to create a useful and reusable AjAX framework with Zend.
The Goal
This tutorial will explain how to create a reusable UI AJAX layer with dojo that communicates to the Zend controller class. I’ll provide some basic code that will show you one way of creating a reusable framework that makes it easier to organize your javascript/ajax and controller layer.
Prerequisites
Before you proceed, you’ll need to read up on how to setup the Zend MVC framework.
The Steps
1. Setup the Zend Framework and a MVC structure
2. Create the controller class file (e.g. – MidstrideController.php)
3. Create the view folder “midstride” in the view/scripts directory.
4. Create the file “index.phtml” in the midstride views/scripts folder.
5. Create an empty javascript file called ajaxmethods.js and place it in your javascript folder.
-check up-
Your file structure should look something like this now:
-/application/controller/MidstrideController.php
-/application/views/scripts/midstride/index.phtml
-/www/javascript/ajaxmethods.js
-/www/scriptslib/dojo-release-1.1.1
Where application is your MVC folder and www is the directory for your assets and index.php bootstrap file.
5. Add the javascript code to the header of index.phtml
<script type="text/javascript" src="<?php echo $this->baseUrl; ?>/javascript/ajaxmethods.js"></script>
<script type="text/javascript" src="<?php echo $this->baseUrl;?>/scriptslib/dojo-release-1.1.1/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
</script>
In this case, the baseUrl is a short cut variable defined in your controller class
e.g. – $this->view->baseUrl = $this->_request->getBaseUrl(); //gets the root of your application
6. Add some sample form information to index.phml
<div id="status_message"><!-- ajax messages go here--></div>
<form id="ajax_form">
<input type="text" name="test_input" value="12345" />
<input id="submit_button" type="submit"
value="submit"
onclick="formPost('<?php echo $this->baseUrl ?>/midstride/ajaxcall',"ajax_form","ajax_loader","submit_button") />
<div id="ajax_loader" class="ajax_loader" style="display:none;" />
</form>
This form will call the javascript function “formPost” with the id of the ajax loader which is currently hidden. The next step is to define the javascript function which will do the ajax call.
7. Code a reusable javascript ajax function
function formPost(destinationUrl, formId, loaderId, submitId)
{
var useAjaxLoader= true;
var hideSubmitAction = true;
if (loaderId===undefined) { useAjaxLoader = false; }
if (submitId===undefined) { hideSubmitAction = false; }
var postParams = { url: destinationUrl,
load: function(data) {
dojo.eval(data);
//hide ajax loader
if (useAjaxLoader) { dojo.byId(loaderId).style.display = "none";}
if (hideSubmitAction) { dojo.byId(submitId).style.display = "";} },
error: function(data) { console.debug("An error occurred: ", data); },
form: formId,
timeout: 4000,
headers: { "X-Requested-With": "XMLHttpRequest" }
};
//show ajax loader
if (hideSubmitAction) {dojo.byId(submitId).style.display = "none";}
if (useAjaxLoader) {dojo.byId(loaderId).style.display = "";} //block
dojo.xhrPost(postParams);
}
There’s a lot going on in this code but it’s not that complex. In short:
- destinationUrl = the HTTP address you want to call (a controller action method).
- formId = the id of the form that is making the call.
- loaderId = the id of the ajax loader (optional)
- submitId = the id of the submit button (optional)
The loaderId and submitId are used to show a loading icon and hide the submit button. This provides the nice ajax feedback and makes sure the user doesn’t click twice.
The destinationUrl is the same address as in the GET or POST URL. We need to pass the formId so that the parameters can be passed. I’ll explain at the end other ways of passing parameters.
8. Create some sample php code in the controller class “MidstrideController.php”
[in MidstrideController.php]
public function ajaxcallAction()
//only handle ajax calls
if ($this->_request->isXmlHttpRequest())
{
//don't render the page - no view script is needed{
$this->_helper->viewRenderer->setNoRender();
//json is the intermediate language to pass messages between the server and client
$jsonData = ""; //initialize to nothing
//get the parameter as normal
$testValue = $this->_request->getParam("test_value");
//prepare a fancy highlight response back
$jsonData = "var highlight = dojo.animateProperty(
{
node: 'status_message',duration: 500,
properties: {
color: { start: 'white', end: 'black' },
backgroundColor:{ start: '#fffecc', end: '#ffffff' }
}
});highlight.play();"
$this->_response->appendBody($jsonData);
}
}
This action method listens for the ajax called made by the javascript function. It only deals with XmlHttpRequests (AJAX) and then sets the controller to not render anything. The no rendering option means you don’t need to create a view (phtml) script. Next, you just handle the form data as you would normally and prepare a JSON response to send back. In this case, I’ve prepared a dojo animation to make a nice highlight on a status box. In practice, you may not want to include any javascript in your controller class, as this is technically UI logic that could be in the ajax (JS) layer. I prefer including dojo javascript because I don’t like writing javascript .
The last call $this->_response->appendBody($jsonData) returns a javascript string which is evaluated in your javascript function by dojo.eval(data).
You’re done
That’s it! You now have a simple way of making ajax calls and keeping your main logic in the controller layer, where it should be. If you wanted to pass more parameters to the controller class, you would have to modify the formPost() function to have this:
contentParams = { “paramOne”:”1″,”paramTwo”:”2 };
and then pass this to the var post params like:
var postParams { content:contentParams, …other parameters}
This can be useful when you have hidden values or other non traditional form inputs to pass in.
Pros
-8 steps to a reusable ajax layer.
-You can easily customize the ajax post effects with dojo’s large animation library.
-A very customizable and flexible framework for any project.
Cons
-Technical level: It can take a while to learn the MVC and Dojo library.
Conclusion
That wraps up my first article on AJAX and the Zend Framework. Future upcoming AJAX articles will discuss how to integrate Zend in scenarios where you want a real progress bar, modal popups, and captcha services. Please let me know if you have any comments or questions.