Some AJAX Zend style with JQUERY

I recently had the opportunity to work on a piece of code that was to accept a couple of values based on a couple of drop-down selectors. The second of the selectors needed to be relative to the value selected in the first one. This was part of a project that uses the Zend Framework. In order to not compromise my NDA, I am changing the particulars, but the nature of the task remains true. To that end, I will start by setting the environment. As stated, I am using the Zend Framework and implementing the MVC design pattern that ZF is known for. I am using the Zend_Layout extension and have the standard application/layouts/scripts folder with a “layout.phtml” file containing my overall layout. I am using just the Controller/Action setup rather than the Module/Controller/Action one, so if you are utilizing modules, then you will need to adjust this to your environment. I also use Zend_Form to create my form input and you will see some example code based on this a little later that will show two drop-down selectors defined on a form. The first drop-down selector will be called Category and the second drop-down selector will be called SubCategory. I know, how original! So, now that the background is laid out, lets start by defining the solution I am setting out to accomplish here.

What I want to do is have the SubCategory drop-down be filled based on the value of the Category drop-down. So, whenever the Category selection changes we want to issue an ajax call back to the server to get a list of SubCategories based on the current Category. To accomplish this, we need to define both drop-down selectors. Here is a snippit of the code that defines them in a Zend_Form extended class:

$categories = Application_Model_CategoryTable::getCategoriesSelectList();
$category_id = 0;
$selectCategory = $this->createElement('select','category');
foreach ($categories as $category) {
    if ($category_id == 0) { $category_id = $category['id']; }

$subcategories = Application_Model_SubcategoryTable::getSubcategoriesByCategorySelectList($category_id);
$selectSubcategory = $this->createElement('select','subcategory');
foreach ($subcategories as $subcategory) {

As you can see, I am also using Doctrine, but using some other database connectivity methodology would simply be a matter of replacing the calls to Doctrine classes with calls to the classes you use instead. Also, in order to use ajax, I wanted to include the jquery script here within the form so that it is only loaded when this form is loaded and also so that I did not have to define or include it in multiple locations to account for adding versus editing. Since I use the same form for both adding and editing, this seems the logical place to put the javascript required for the ajax call. There is a nice little helper available for forms that lets you place html code within the form and since the script tag is part of html code, this works just fine. In my case, because I use this form for both adding and editing, I have a hidden element already in place for the ‘id’ field for the record being maintained here. So, here is that code and the bit to add html code to the form:

$hid = $this->createElement('hidden', 'id');
 'viewScript' => 'record/_record-form-js.phtml',

This bit of code will simply attach the “ViewScript” decorator to the hidden id element. The path specified for this is relative to the ‘views/script’ folder and it makes sense to store the included file along with the view scripts for the controller this is being done for, “record” in our example. I know, another original name!!!  Now, lets take a look at the “_record-form-js.phtml” file:

<script type="text/javascript">
    var id=$(this).val();
    var dataString = "make_id="+ id;

        type: "POST",
        url: "/ajax/get-subcategory-by-category-option-list",
        data: dataString,
        cache: false,
        success: function(html)



This is a jquery script that checks for a change to the ‘#category’ element and then fires off an ajax call that upon success will update the innerHtml of the ‘#subcategory’ element with the response from the ajax call. You can also see that the ajax call seems to be just a simple call to a controller/action of the ZF based application. As you may or may not know, this typically results in a full response with all your layout and such, which is not what we want for an ajax call. I reviewed a number of ways to implement this and tried for a while before coming up with what I feel is a very simple solution. I have a controller called AjaxController that extends the Zend_Controller_Action just as most controllers do, however I make a few changes to get it to behave the way I want it to. One of the changes is to add an init() function that simply sets the layout to a new file which only displays the controller/action contents and has no other layout to it. I call this new layout “ajax.phtml” and it is also located in the layout/scripts folder with the normal “layout.phtml” file. The contents of “ajax.phtml” are the one line which reads “<?php echo $this->layout()->content; ?>” and this allows us to return only the results of the action called in the AjaxController. Here is what the controllers/AjaxController.php file looks like:

class AjaxController extends Zend_Controller_Action {
  public function init()   {

  public function resultsAction()

  public function getSubcategoriesByCategoryOptionListAction()
    $category_id = $this->_request->category_id;

    $subcategories = Application_Model_SubcategoryTable::getSubcategoriesByCategorySelectList($category_id);

    $result = '';
    foreach ($subcategories as $subcategory) {
      $result .= '<option value="' . $subcategory['id'] . '">' . $subcategory['description'] . '</option>';

    $this->view->result = $result;


Notice that the init() function changes the layout as stated above, and that there is an empty “resultsAction” method. You can see that at the end of the getSubcategoriesByCategoryOptionListAction method there is a “$this->render('results')” statement. This allows me to have many methods defined in this controller for fetching various information and as long as I capture that information as html markup in a variable called ‘result’ and I assign that variable to the view, then this render statement allows me to have only one view script for all the methods in this controller and it is called “results.phtml” and it resides in the view/scripts/ajax folder, the contents of which are one line containing “<?php echo $this->results; ?>“. Of course, if the need arises for more complex content to be returned, then you can simply create the normal view script for the method as you would for any other controller action and just omit the $this->render(‘results’) statement at the end of the action.

This has resulted in a very easy way to implement ajax calls for a web 2.0 type effect with very little headache. And now that it is done, the next one will be no headache at all.

Leave a Reply

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