Tab Container Enabled Forms

Nathan Garlington wrote a nice solution for Tab based forms; Yes, it is possible to display a form in a tabContainer. I do it all the time, including using other dijit containers as well. keep in mind that this is just my solution…there are probably other ways to do this. Feel free to customize it according to your needs. Also, you may notice that I don’t include an action attrib or method attrib declaration to the form node itself…this is because I handle form submitting via xhr. Example code below:


class My_Form extends Zend_Dojo_Form
{
public function init()
{
$this->setDisableLoadDefaultDecorators(true);

// setup the our default decorators
$this->setDecorators(array(
'FormElements',
array('TabContainer', array(
'id' => 'myTabContainer',
'style' => 'width: 950px; height: 420px;',
'dijitParams' => array('tabPosition' => 'top'),
)),
'DijitForm',
));

$this->setName('myAddTrailerForm');

$this->setElementDecorators(array(
array('DijitElement'),
array('Description'),
array('HtmlTag', array('tag' => 'dd')),
array('Label', array('tag' => 'dt')),
));

//call custom class methods to add form members
$this->_addElements()
->_addDisplayGroups();

}

private function _addElements()
{
$this->addElements(array(

// general information display group elements
new Zend_Dojo_Form_Element_FilteringSelect('field1', array(
'label' => 'First Field:',
'multiOptions' =>(array(
'option1' => 'option1',
'option2' => 'option2'
)),
'required' => true,
)),

new Zend_Dojo_Form_Element_CheckBox('cb1', array(
'label' => 'Are you sure?:',
)),

new Zend_Dojo_Form_Element_FilteringSelect('year', array(
'label' => 'Year:',
'multiOptions' => array(/*....*/),
'required' => true,
)),

new Zend_Dojo_Form_Element_ComboBox('comboBox1', array(
'label' => 'ComboBox1:',
'multiOptions' => array(/*....*/),
'required' => true,
'autocomplete' => false,
'attribs' => (array('propercase' => true, 'trim' =>true)),
)),

new Zend_Dojo_Form_Element_ValidationTextBox('validationBox1', array(
'label' => 'ValidationBox1:',
'required' => true,
'attribs' => array('uppercase' => true, 'trim' =>true),
)),

new Zend_Dojo_Form_Element_ValidationTextBox('validationBox2', array(
'label' => 'ValidationBox2:',
'required' => true,
'invalidMessage' => "Please enter a value",
'attribs' => array('maxlength' => 17, 'uppercase' => true, 'trim' =>true),
'filters' => array('StringToUpper'),
'validators' => array('Alnum'),
)),
)); // end $this->addElements

return $this;
} // end _addElements()

/**
* Create the tabbed container layout
*/
private function _addDisplayGroups()
{

// add the display groups
$this->addDisplayGroup(
array( // elements in the displayGroup
'field1',
'cb1'
),
'generalInformation' // displayGroupName
);

$this->generalInformation->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'dl')),
array(
'ContentPane', array(
'title' => 'General Information'
)
)
));

$this->addDisplayGroup(
array(
'year',
'comboBox1',
),
'tab2'
);

$this->tab2->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'dl'),
array(
'ContentPane', array(
'title' => 'Tab 2'
)
)
));

$this->addDisplayGroup(
array(
'validationBox1',
'validationBox2',
),
'tab2'
);

$this->tab2->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'dl', 'class' => 'addTrailer')),
array(
'ContentPane', array(
'title' => 'Axles'
)
)
));

return $this;
} // end _addDisplayGroups();

public function buttonsSubForm()
{
$subForm = new Zend_Dojo_Form_SubForm();
$subForm->setDecorators(array(
'FormElements',
array('HtmlTag', array('tag' => 'div', 'id' => 'buttonsSubForm', 'class' => 'span-7 push-3 prepend-top')),
))
->setElementDecorators(array(
array('DijitElement'),
))
->addElements(array(
new Zend_Dojo_Form_Element_Button('submit', array(
'type' => 'button',
'label' => 'Submit it!',
'attribs' => array('disabled' => 'disabled'),
)),

new Zend_Dojo_Form_Element_Button('cancel', array(
'label' => 'Cancel',
)),
));
$subForm->submit->removeDecorator('DtDdWrapper');
$subForm->cancel->removeDecorator('DtDdWrapper');
return $subForm;
} // end buttonsSubForm();
} // end class

That’s it. There may be some errors in there, but the idea is there. As you can see, once you see you how it goes together, it’s actually trivial to add dijit layout containers to a zend form. Be sure that you are in fact extending Zend_Dojo_Form, or using one of the other methods shown in the docs for dojo-enabling your form. You may or may not like the buttons subForm I use here either…I do this because otherwise the submit buttons have to be in their own tab, and that makes it confusing for some of my users…they don’t know where the buttons are to submit the form. So I display them in a div that renders outside the tab container, disable the submit button, and using dojo’s methods, I enable the button on the onValidStateChange dojo event. Let me know if you have any questions!

regards,
Nathan Garlington

Easy command line scripts with Zend Application

David Caunt wrote up a useful article on command line scripting;

As PHP developers, it is convenient to be able to write command line scripts in PHP. In doing so, you will almost certainly want access to Zend Framework components and their configurations as if you are writing a normal MVC app, but without invoking the MVC stack and without loading unnecessary resources. I’ve seen solutions where actions are exposed as controller actions and called by wget – these are counter-intuitive, inefficient, and will suffer from max execution timeouts and other problems.

Zend_Applicaton to the rescue

Lets start with our website’s public/index.php – the script which sets up and launches an application. It looks roughly like this:

full article here; Easy command line scripts with Zend Application.

Zend_Form Decorators Explained

Jon Lebensold posts another great screen cast about one of the most confusing parts of Zend Framework ever created 🙂 ;

One of the pain points for folks who are starting to work with the Zend Framework is the Decorating functionality found in the depths of Zend_Form. I’ve witnessed countless instances when a developer becomes excited by Zend_Form’s easy-to-implement form validation and creation, only to become frustrated by countless hours of fighting with Zend_Form_Decorators. This video is a humble attempt on my part to walk through how Zend_Form Decorators work and how you can reason your way through a desire result. I couldn’t have gotten my own head around this implementation of the decorator pattern without Matthew Weier O’Phinney’s excellent posts and his original devzone article.

UPDATE: check out this blog post / tutorial for ZF 1.10.0: http://framework.zend.com/manual/en/learning.form.decorators.html

I’ll show you a bit about how Zend_Form_Decorators are constructed and how to take the default zend_form layout and transform it into a table.

Grab a copy of the project or browse the repository.

via Zendcasts.

Zend_Translate with Dynamic Parameters

Pascal Opitz posted a nice little snippet; Just a quick snippet to have dynamic parameters in the underscore function, without having to write sprintf every time.

<?php
class Translate extends Zend_Translate {
  public function _() {
    $args = func_get_args();
    $num = func_num_args();

    $adapter = $this->getAdapter();

    $args[0] = $adapter->_($args[0]);

    if($num <= 1) {
      return $args[0];
    }
    return call_user_func_array('sprintf', $args);
  }
}

Usage would be something like the following:

$t = new Translate('array', $array_translation, $lang);
echo $t->_('My name is %s', 'Pascal');
echo $t->_('I have a %s and a %s', 'Cat', 'Horse');

Note: The above little snippet solves one of the major gripes I have with the default _() function.

via Zend_Translate with dynamic parameters.

Zend_Validate messages translated to Swedish

Thomas Wei­d­ner commits the hackix.com Swedish translations to trunk.

Danny spent some time translating the ~200 validation messages in /resources/languages/sv/Zend_Validate.php make sure to give them an eye over after your next trunk (1.10.2+) checkout and report any suggestions & feedback here.

Zend_Translate & TMX adapter – Source language strings as id

Thomas Weidner describes some additional functionality only available from Zend Framework 1.10.2+ and forward, for those of us that do *not* wish to use a separate message id/key but rather the source language string in the source code.

Set the “useId” option to false.
In this case the source language is used as message key and the source must be set as first translation.





Nachricht 1
message 1


Note the ‘useId’ => false below;

$translate = new Zend_Translate('tmx', $file, $locale, array('useId' => false));

Then “Nachricht 1” will be used as message key instead of “0001”.
Note that this works only as with 1.10.2 (or trunk as of today).

App_Controller_Helper_Params for JSON and XML POSTs

Matthew Weier O’Phinney shares a bit of very useful code to inject request params into a Zend Framework request object from a JSON or XML POST request.

“Below is a plugin I use to translate JSON or XML raw post request data to request user parameters.
Note that it expects a “Content-Type” header of either “application/json” or “application/xml”. If those are detected, it then does the translation and injection.
Once it has, you can then simply access the parameters from your request object like any others.
I actually use this with dojox.data.JsonRestStore already, so you should be set. :)”

class App_Controller_Helper_Params extends Zend_Controller_Action_Helper_Abstract { 
/**
 * @var array Parameters detected in raw content body
 */
 protected $_bodyParams = array(); 
/**
 * Do detection of content type, and retrieve parameters from raw body if
 * present
 *
 * @return void
 */
 public function init() {
 $request = $this->getRequest();
 $contentType = $request->getHeader('Content-Type');
 $rawBody = $request->getRawBody();
 if (!$rawBody) {
   return;
 }
switch (true) {
 case (strstr($contentType, 'application/json')):
   $this->setBodyParams(Zend_Json::decode($rawBody));
   break;
 case (strstr($contentType, 'application/xml')):
   $config = new Zend_Config_Xml($rawBody);
   $this->setBodyParams($config->toArray());
   break;
 default:
   if ($request->isPut()) {
    parse_str($rawBody, $params);
   $this->setBodyParams($params);
 }
 break;
 }
}

/**
* Set body params
*
* @param array $params
* @return Scrummer_Controller_Action
*/
public function setBodyParams(array $params)
{
  $this->_bodyParams = $params;
  return $this;
}

/**
* Retrieve body parameters
*
* @return array
*/
public function getBodyParams()
{
  return $this->_bodyParams;
}

/**
* Get body parameter
*
* @param string $name
* @return mixed
*/
public function getBodyParam($name)
{
  if ($this->hasBodyParam($name)) {
    return $this->_bodyParams[$name];
  }
  return null;
}

/**
* Is the given body parameter set?
*
* @param string $name
* @return bool
*/
public function hasBodyParam($name)
{
  if (isset($this->_bodyParams[$name])) {
    return true;
  }
  return false;
}

/**
 * Do we have any body parameters?
 *
 * @return bool
 */
 public function hasBodyParams()
 {
   if (!empty($this->_bodyParams)) {
     return true;
   }
   return false;
 }
 
 /**
 * Get submit parameters
 *
 * @return array
 */
 public function getSubmitParams()
 {
   if ($this->hasBodyParams()) {
     return $this->getBodyParams();
    }
   return $this->getRequest()->getPost();
 } 

 public function direct()
 {
   return $this->getSubmitParams();
 }
}