Simple Zend Framework and Ajax Tutorial

Zend FrameworkI love the Zend Framework. I’ve been using it since version 1.5 (currently at 1.10 as of this writing). It has so many features and can do so many things–sometimes it’s just not immediately clear how to implement those great features.

One feature that took me awhile to figure out was AJAX context switching. The documentation contains various pieces of information about implementing AJAX, but it just wasn’t clear how to put those pieces together. To help make this more clear, I’m going to go through a simple example of how to add very basic AJAX to the Zend Framework QuickStart project. I’m going to be using jQuery because I prefer that to Dojo and the rest of the JavaScript frameworks.

This tutorial assumes you already have a development server set up, Zend Framework installed, and the Zend Framework QuickStart project up and running.

Modify IndexController.php

First we need to set up Ajax context switching in the main controller. Add the following init() function to the index controller found in controllers/IndexController.php

public function init()
{
    $ajaxContext = $this->_helper->getHelper('AjaxContext');
    $ajaxContext->addActionContext('list', 'html')
                ->addActionContext('modify', 'html')
                ->initContext();
}

The html parameter is the type of Ajax request. You can also use JSON or XML.

Note: The modify context is not used in this tutorial but is merely there to demonstrate that you can have as many action contexts as you want.

Now we need to add the list action that we specified above in the addActionContext call to the IndexController.php.

public function listAction() {
    // pretend this is a sophisticated database query
    $data = array('red','green','blue','yellow');
    $this->view->data = $data;
}

Create the list view scripts

By default, Zend Framework tries to render view scripts with the same name as the action. If our action’s name is list and is controlled by the controller named index, then Zend will try to render a view script located at view/scripts/index/list.phtml. Since we are using Ajax context switching, Zend Framework attempts to render view/scripts/index/list.ajax.phtml instead.

For testing my Ajax actions I usually create a normal view helper as well as the Ajax helper but then just include the Ajax view helper.

Create the following view scripts. The second script list.phtml is optional but might aid in troubleshooting.

views/scripts/index/list.ajax.phtml

<!-- views/scripts/list.ajax.phtml should contain something like the following -->
<ul>
<?php foreach ($this->data as $color) : ?>
<li><?= $color ?></li>
<?php endforeach; ?>
</ul>

views/scripts/index/list.phtml

<?php
include('list.ajax.phtml');

jQuery time

The last thing we need to do is to add some HTML and JavaScript to our index.phtml view script to test everything out.

Add the following to the bottom of views/scripts/index/index.phtml

<div id="container">
</div>
<script type="text/javascript">
  $(document).ready(function() {
        $('#container').load('/default/index/list/format/html');
  });
</script>

The most important part of that jQuery code is the content of the URL you specify. This is one of those cases when you need to specify the module and controller and action even if they are set to the default value.

‘/module/controller/action/format/html’

You must also not forget the format/html part. If you forget it, you’ll notice that Zend is rendering your layout too instead of just rendering the view script.

That’s it. You should now have a list of colours on the first page of your site.

UPDATE: there was an error in the jQuery code on the index.phtml view script. The code is correct now. I have also added a working project to my Google Code repository. Thanks to the commenters for pointing this out.

FacebookTwitterGoogle+LinkedInBufferShare

18 comments

  1. im testin your code but its not working. i was given the path in layout.php file i.e headScript()->appendFile($this->baseUrl().’/js/jquery.js’, ‘text/javascript’)?>
    its include in the page but not call the list function

  2. Errr,
    I think the problem is the following line:
    $(‘#container’).load(‘/index/index/list/format/html’);
    There is one “index” to much.
    -> index/index/ will load the indexAction
    But we want the listAction, so change it to:
    $(‘#container’).load(‘/index/list/format/html’);
    an it will work for ya!

    Allright fellows!

  3. Hi Folks,
    There is still some problem in above code, after implementing it still the code not works.
    Here are few steps to check the problem -
    1. Make sure that “list.ajax.phtml” resides in this directory “{site}/application/views/scripts/index/”.
    2.And this call ” $(‘#container’).load(‘/index/list/format/html’); ” must be changed to ” $(‘#container’).load(‘./index/list/format/html’); ”

    These steps sorted out my problem , may be it will help others too.

    Cheers !

  4. Sorry guys; I dont see the need of this.

    Just create a dedicated controller for your ajax calls, disable layout and renderer and use ZF AjaxLink()

    cheers

  5. Instead of using include, check out the partial view helper:

    echo $this->partial(‘index/list.ajax.phtml’, array(‘data’ => $this->data));

    Also, the url view helper is a very useful:

    echo $this->url(array(‘controller’ => ‘index’, ‘action’ => ‘list’, ‘format’ => ‘html’));

  6. Thanks a lot. Your comment really helped!


    Binod Shukla:

    Hi Folks,
    There is still some problem in above code, after implementing it still the code not works.
    Here are few steps to check the problem -
    1. Make sure that “list.ajax.phtml” resides in this directory “{site}/application/views/scripts/index/”.
    2.And this call ” $(‘#container’).load(‘/index/list/format/html’); ” must be changed to ” $(‘#container’).load(‘./index/list/format/html’); ”
    These steps sorted out my problem , may be it will help others too.
    Cheers !

  7. Finally worked perfectly! Just do one thing – Do not use exit; at the end of the controller action similar to the normal AJAX POST actions.

    Good Job :)

  8. It should go in your Controller like this:

    class IndexController extends Zend_Controller_Action
    {
    public function init()
    {
    $this->_helper->layout->disableLayout();
    }
    }

  9. Isn’t this disable layout for both normal and ajax version? Adding setLayout in indexAction sets layout again for both.

  10. you can use isXmlHttpRequest to detect if ajax request.

    public function init()
    {
    // disable layout and view if ajax request
    if ($this->getRequest()->isXmlHttpRequest()) {
    $this->_helper->layout->disableLayout();
    $this->_helper->viewRenderer->setNoRender(true);
    }
    }

  11. I did this without AjaxContext! just create an Action, layout disabled then paste HTML into view file.
    call ajax using $.load();
    Its working for me, I want know why all are preferring AjaxContext and how my code worked?

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>