My Very First Steps with Zend_Dojo
Wednesday, August 20th, 2008Even though I feel pretty tired this evening, I had to satisfy my curiosity and took a quick look at Zend_Dojo.
My first result: (Click on the picture to see the demo)
Looks quite nice. If you (like me) don’t know the Dojo Toolkit yet, you probably need some time to understand the documentation. It would have been easier to play around with Dojo independently from the Zend_Dojo stuff for some time, but as long as there is no time pressure on you, trial and error can be fun too. I simply tried to follow the Zend_Dojo documentation. First of all you need to tell the view object where it can find the Zend_Dojo ViewHelpers. I’m doing this in my bootstrap file (I’m using the default directory structure like it is described in the docs):
error_reporting(E_ALL|E_STRICT);
set_include_path('../library' . PATH_SEPARATOR . get_include_path());
require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();
$layout = Zend_Layout::startMvc();
// Tell the view where it finds Zend_Dojo ViewHelper
$layout->getView()->addHelperPath('Zend/Dojo/View/Helper/', 'Zend_Dojo_View_Helper');
$front = Zend_Controller_Front::getInstance();
$front->addControllerDirectory('../application/controllers');
$front->throwExceptions(true);
$front->dispatch();
Next step is to include the Dojo library. Because this belongs into the <head> part of your HTML document, I’m changing my layout file (layout.phtml):
<html>
<head>
<title>roetgers.org Dojo Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<?php
// My own stylesheet
echo $this->headLink()->setStylesheet('/css/my.css');
// Check if dojo library is needed
if ($this->dojo()->isEnabled()):
// Include dojo library
$this->dojo()->setLocalPath('/js/dojo/dojo.js')
// Use dojo theme tundra
->addStyleSheetModule('dijit.themes.tundra');
// Echo out the dojo <script> tags
echo $this->dojo();
endif; ?>
</head>
<!-- Set body class to "tundra" -->
<body class="tundra">
<?php echo $this->layout()->content ?>
</body>
</html>
After those changes my application is prepared to use Dojo. In the beginning of a view script you need to tell the ZF, that Dojo is needed by calling
If you don’t do this, the Dojo library will not be included in your layout.phtml file and Dojo won’t work. My first target was to create a TabContainer. Of course there is a ViewHelper which you can use to create such a container:
Looks like a normal ViewHelper. But there is a difference because all layout containers know the capture methods captureStart() and captureEnd():
I really like this way of adding content into a container, because your view script stays readable even if you start nesting containers into containers. Let’s have a look at my complete view script which I used for my sample:
$this->dojo()->enable();
// Container with tabs
$this->tabContainer()->captureStart('tab1', array(), array('style' => 'width:800px;height:500px;'));
// First tab "Dates"
$this->contentPane()->captureStart('pane1', array(), array('title' => 'Dates'));
echo $this->form1;
echo $this->contentPane()->captureEnd('pane1');
// Second tab "FAQ"
$this->contentPane()->captureStart('pane2', array(), array('title' => 'FAQ'));
echo '<h1>FAQ</h1>
<dl><dt>Question 1?</dt><dd>This is my answer 1!</dd></dl>
<dl><dt>Question 2?</dt><dd>Good question, next one.</dd></dl>
<dl><dt>Question 3?</dt><dd>Ok, that\'s enough!</dd></dl>
';
echo $this->contentPane()->captureEnd('pane2');
// Third tab "Closable"
$this->contentPane()->captureStart('pane3', array(), array('title' => 'Closable', 'closable' => true));
echo 'You can close me!';
echo $this->contentPane()->captureEnd('pane3');
// Fourth tab "Splitted"
$this->contentPane()->captureStart('pane4', array(), array('title' => 'Splitted'));
$this->splitContainer()->captureStart('split1', array(), array('style' => 'width:250px;height:250px;'));
$this->contentPane()->captureStart('splitpane1', array(), array());
echo 'Hey, I am on the left side!';
echo $this->contentPane()->captureEnd('splitpane1');
$this->contentPane()->captureStart('splitpane2', array(), array());
echo 'Cool!';
echo $this->contentPane()->captureEnd('splitpane2');
echo $this->splitContainer()->captureEnd('split1');
echo $this->contentPane()->captureEnd('pane4');
echo $this->tabContainer()->captureEnd('tab1');
As you can see every tab is a new ContentPane. ContentPanes can be used inside every layout container except the AccordionContainer. Have a look at the docs for more information on that.
I’m displaying a form in the first tab. This form is an object of the class Zend_Dojo_Form. There are some really cool Dojo widgets (Dijits) which you can use to spice your forms up. The form is created in my IndexController:
{
$form1 = new Zend_Dojo_Form();
$form1->setMethod('post')->setAction("/");
$form1->addElement('DateTextBox', 'date1', array(
'label' => 'Choose a date:',
'datePattern' => 'yyyy-MM-dd',
'validators' => array('Date'),
'required' => true
))
->addElement('TimeTextBox', 'time1', array(
'label' => 'Choose a time:',
'timePattern' => 'HH:mm:ss',
))
->addElement('NumberSpinner', 'number1', array(
'label' => 'Choose a number:',
'value' => 0,
'smallDelta' => 1,
'min' => 0,
'max' => 30,
'defaultTimeout' => 100,
'timeoutChangeRate' => 100,
))
->addElement('HorizontalSlider', 'slide1', array(
'label' => 'Let\'s slide:',
'minimum' => 0,
'maximum' => 25,
'discreteValues' => 10,
'style' => 'width: 450px;',
'topDecorationDijit' => 'HorizontalRuleLabels',
'topDecorationLabels' => array('0%', '50%', '100%'),
'topDecorationParams' => array('style' => 'padding-bottom: 20px;'),
))
->addElement('SubmitButton', 'submit', array(
'label' => 'Submit!'
));
$this->view->form1 = $form1;
}
As you can see it is ridiculous easy to put together such a form. Basically it is the same as with the normal Zend_Form. Of course the Dojo form elements have different names (e.g. “SubmitButton” instead of “submit”) and you need some additional array keys in the form element configuration but then the magic happens.
This is only the very first step on my way of understanding Dojo but so far it looks promising! I’ll write more about it as soon as I digged deeper into that topic.
Tags: Dojo Toolkit, Javascript, PHP, Zend Framework, Zend_Dojo



















August 20th, 2008 at 3:30 pm
If I understand correctly, the viewhelpers (like the tabContainer) are only usable in the view script and not in the layout script? Because if it is, this would be very useful. Else I’d have to put the same code in all of the view scripts, while the layout script should help avoid this.
If not, would I be able to access the viewHelpers like so in my layout script:
$this->getView()->tabContainer(…)?
thx
August 21st, 2008 at 11:18 am
A layout script behaves similar to a view script. So of course you can use the dojo view helpers in the layout script in the same way you use them in a view script, e.g. echo $this->tabContainer($what, $ever);
The only problem is, that the dojo view helper, which builds all the javascript tags in the <head> part of your html document, only knows which parts of the Dojo Toolkit are needed, if you used them before. That means if you build up your layout script like I described it in my blog post and then add some dojo stuff in the <body> area of your layout script, the view helper which you used in the <head> part don’t know about that, because it happens after the helper is called. As far as I oversee that in the moment, you have two options: Build the dojo stuff _before_ the <head> part in your layout script but print it out _after_ the <head> part or tell the dojo view helper which dojo modules are required before you use them like this:
$this->dojo()->enable()
->setDjConfigOption(’parseOnLoad’, true)
->registerModulePath(’../whatever/’)
->requireModule(’dijit.form.DateTextBox’)
->requireModule(’dijit.layout.TabContainer’)
->requireModule(’etc, etc’);
It’s described here: http://framework.zend.com/manual/en/zend.dojo.view.html#zend.dojo.view.dojo
Maybe there is an easier way. As I said that was my first little test with Zend_Dojo and the Dojo Toolkit, I don’t know all the details yet.
August 21st, 2008 at 12:42 pm
Like so?
//layout script:
$tab1 = $this->tabContainer(…);
doctype() ?>
if ($this->dojo()->isEnabled()):
$this->dojo()->setLocalPath(’/js/dojo/dojo.js’)
->addStyleSheetModule(’dijit.themes.tundra’);
echo $this->dojo();
endif; ?>
tab1;
$this->layout()->content;
?>
August 21st, 2008 at 12:44 pm
edit:
$this->tab1; or $tab1;
August 21st, 2008 at 1:47 pm
Here is a sample layout.phtml which works:
$this->dojo()->enable();
$this->tabContainer()->captureStart('tab1', array(), array('style' => 'width:800px;height:500px;'));
// First tab "Pane 1"
$this->contentPane()->captureStart('pane1', array(), array('title' => 'Pane 1'));
echo 'ContentPane1';
echo $this->contentPane()->captureEnd('pane1');
// Second tab "Pane 2"
$this->contentPane()->captureStart('pane2', array(), array('title' => 'Pane 2'));
echo 'ContentPane2';
echo $this->contentPane()->captureEnd('pane2');
$tab = $this->tabContainer()->captureEnd('tab1');
echo $this->doctype() ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>roetgers.org Dojo Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<?php
echo $this->headLink()->setStylesheet('/css/my.css');
if ($this->dojo()->isEnabled()):
$this->dojo()->setLocalPath('/js/dojo/dojo.js')
->addStyleSheetModule('dijit.themes.tundra');
echo $this->dojo();
endif;
?>
</head>
<body class="tundra">
<?php echo $tab ?>
<?php echo $this->layout()->content ?>
</body>
</html>
August 21st, 2008 at 6:17 pm
Thx a lot!!!
September 3rd, 2008 at 9:17 am
I did not enable dojo in my view script, even I disabled it, however, the dojo library was still included in my layout.phtml. I already followed your steps, why?
September 3rd, 2008 at 9:25 am
I found that if I echo a zend form in my view script it will enable dojo automatically regardless calling $this->dojo()->disable().
// like this:
// In my view script
$this->dojo()->disable();
echo $this->form; // Generated by Zend_Form
// In my layout
if ($this->dojo()->isEnabled()) { // This will return true.
….
}
September 3rd, 2008 at 11:21 am
I guess this isn’t Zend_Form but Zend_Dojo_Form, is it? If that’s the case, it would make sense to activate dojo automatically.
September 3rd, 2008 at 1:21 pm
Very nice tut but i miss the inter component action, the replacement of parts of the screen where the ajax paradigm stands for. For example Zend + Dojo forms and grids that run alternating in the same tab steered by a navigation tree without refesh of the whole page. An idea for your Next Steps with Zend_Dojo?
September 3rd, 2008 at 2:03 pm
Unfortunately I didn’t make any progress with the Dojo Toolkit. In my current project at work the combination of Prototype/Scriptaculous is still used, so I didn’t had the chance yet to dig deeper into Dojo at work.
Probably Matthew’s webinar today will cover a lot of stuff which isn’t mentioned in this blog post.
September 16th, 2008 at 2:52 pm
Very helpful example, thank you a lot. Also looking forward to your next steps, as I’m taking mine at the moment
September 17th, 2008 at 9:49 pm
Very nice tutorial !
I’ve an install problem :
in /public/styles -> put here all the DOJO stuff ?
ie :
/public/styles/dojo/dijit
/dojo
/dojox
/utils
In this case must I use :
if ($this->dojo()->isEnabled()):
$this->dojo()->setLocalPath(’/public/styles/dojo/dojo/dojo.js’)
->addStyleSheetModule(’dijit.themes.tundra’); // How can it find it ????
echo $this->dojo();
endif;
Am I right ?
Gilles
September 19th, 2008 at 2:01 am
Hi, I found your blog on this new directory of WordPress Blogs at blackhatbootcamp.com/listofwordpressblogs. I dont know how your blog came up, must have been a typo, i duno. Anyways, I just clicked it and here I am. Your blog looks good. Have a nice day. James.
September 24th, 2008 at 2:36 pm
Hi! This is really a great example, thanks!
But I’m wondering, why it’s not working in IE?
September 25th, 2008 at 2:59 am
Really great example !
I am looking for a simple example of autocompletion using ZF1.6 with Zend_Dojo class and a database table.
The ZF documentation for that is not usefull for me.
Do you know where I can find some example that really work ?
Thank you
September 26th, 2008 at 11:36 pm
Just wanted to give a heads-up that the tabs seem not to render in Internet Explorer 7.
September 28th, 2008 at 9:30 pm
Thanks for reporting the IE issue. I’ll investigate that next week.
October 9th, 2008 at 5:36 pm
For easy Dojo application, check your Apache http.conf and your .htaccess (same directory as the index.php bootstap). It works perfectly with IE.
ie. httpd.conf
ServerAdmin webmaster@localhost.localdomain
DocumentRoot “c:/travail/www/testdojo/public”
ServerName testdojo
ErrorLog logs/testdojo-error.log
CustomLog logs/testdojo-access.log common
DirectoryIndex index.php
AllowOverride All
Order allow,deny
Allow from all
and the .htaccess (don’t forget to start the corresponding mods in php.ini)
# PHP values we need to set
# - timezone should be set
# - need short open tags for view scripts
php_value date.timezone “UTC”
php_value short_open_tag 1
php_value error_reporting 8191
php_flag display_errors Off
php_flag display_startup_errors Off
# Rewrite Rules
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ /index.php [NC,L]
# Expires/ETags
# You’ll want to turn off the ExpiresActive setting when actively developing.
# In production, however, these settings follow the Y!Slow guidelines.
ExpiresActive On
ExpiresByType text/css “access plus 1 month”
ExpiresByType application/x-javascript “access plus 1 month”
ExpiresByType image/png “access plus 1 month”
ExpiresByType image/gif “access plus 1 month”
FileETag none
# Gzip CSS and JS by default
AddOutputFilterByType DEFLATE text/css application/x-javascript
October 9th, 2008 at 5:39 pm
This is a great example ! thanks !
Just a question, how do you send data from your controller to an textaera element ?
October 9th, 2008 at 11:41 pm
Jean you are a life saver! My example wasn’t working until I fixed my htaccess file. Nice blog Mike, definitely a useful resource.
October 10th, 2008 at 9:19 pm
Note: I’m not sure if it’s because I’m using modules, but to correct Jeans note, change -
RewriteRule ^.*$ /index.php [NC,L]
to
RewriteRule ^.*$ index.php [NC,L]
October 20th, 2008 at 8:53 pm
I had to take it a step further on my rewrite rule and tell it to exclude JS, CSS, etc. This wasn’t a problem with this example, but when putting it inside of a BorderControl, it became quite a problem.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule .* - [L]
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
I found this rewrite rule on Gavin Williams’ blog, just another developer (http://blog.justanotherdeveloper.co.uk/).
November 1st, 2008 at 5:40 am
Very informative! We’re also working with Zf and using prototype & scriptaculous at our workplace. But lately I’ve been making moves to try out Dojo with Zf. It’s awesome! I started learning Dojo independently from Zf. So it was pretty simple to implement Dojo Form Elements.
Good write up man
November 20th, 2008 at 12:59 am
Thank you, thank you, thank you. I’ve been trying to get the Zend_Dojo stuff to work for a couple hours going through various tutorials and none of them have worked until now. I really appreciate it!
November 20th, 2008 at 10:14 am
Hi Mike,
I am the newbie of ZF and facing many problems in ZendFramework. Actually, I’m trying to add Zend_Dojo in combination with AJAX.
Could you help me regarding this thing by putting any example begineer level example?
Could you please provide its complete source code of this Tab container example?
Ilyas
November 27th, 2008 at 2:23 pm
Thanks for the post! very useful