10/11/08

Zend_Dojo_Form and Form Validation on the Client Side

One thing those of you who have been using Zend_Dojo_Form might have noticed is that dojo enabled forms don’t show validation warnings when submitted i.e. when the submit button is clicked. This can be quite confusing for the end user.

So, how do we get our dojo enabled forms to validate when submitted?

Matthew Weier O’Phinney explains on nabble that:

You need to bind to the onSubmit event of your form, and validate in
your callback. One way to do this is as follows, from your view script:

< ? $this->dojo()->javascriptCaptureStart() ?>
function validateForm() {
    var form = dijit.byId("<formid>");
    if (!form.validate()) {
        alert("Invalid form");
        return false;
    }
    return true;
}
< ? $this->dojo()->javascriptCaptureEnd() ?>
< ? $this->dojo()->onLoadCaptureStart() ?>
function () {
    dojo.connect(dijit.byId("</formid><formid>"), "onSubmit", "validateForm");
}
< ? $this->dojo()->onLoadCaptureEnd() ?>
</formid>

What the above does is connect the onSubmit event to the form, which
then executes the validateForm() function; if this returns false,
submission is halted, and, in this case, an alert raised. You could also
popup a dialog box or some other notification.

The above snippet of code Matthew describes doesn’t quite work. An Issue has been created for it here http://framework.zend.com/issues/browse/ZF-4587, but there is a work around, we can use headScript()->capture instead.

Let’s look at how to apply this as a view helper.

The view helper:

library/My/View/Helper/ValidateDojoForm.php

class My_View_Helper_ValidateDojoForm extends Zend_View_Helper_Abstract
{
    public $view;
 
    public function setView(Zend_View_Interface $view)
    {
        $this->view = $view;
    }
 
    /**
     * Validate dojo enabled form onSubmit.
     *
     * @param  string $formId
     * @return void
     */
    public function ValidateDojoForm($formId)
    {
        $this->view->headScript()->captureStart(); ?>
        function validateForm() {
            var form = dijit.byId("< ?php echo $formId; ?>");
            if (!form.validate()) {
                return false;
            }
            return true;
        }
        dojo.addOnLoad(function () {
            dojo.connect(dijit.byId("< ?php echo $formId; ?>"), "onSubmit", "validateForm");
        });
        < ?php $this->view->headScript()->captureEnd();
    }
}

This is very simple view helper. All you need to do is call validateDojoForm in your view script passing in the id of the form you want to be validated on submission as follows:

$this->validateDojoForm('formId');

Helper paths need set up, one way of doing this is in our bootstrap as follows:

/**
 * Initialize view and layouts
 */
$layout = Zend_Layout::startMvc('/path/to/layouts');
$view = $layout->getView()
    ->addHelperPath('My/View/Helper/', 'My_View_Helper')
    ->addHelperPath('Zend/Dojo/View/Helper/', 'Zend_Dojo_View_Helper');

More information on view helpers and helper paths.

What about a custom class that does all the work for us?

A Custom Zend Dojo Form Class

library/My/Dojo/Form.php

class My_Dojo_Form extends Zend_Dojo_Form
{
    /**
     * Set form name
     *
     * @param  string $name
     * @return Zend_Form
     */
    public function setName($name)
    {
        parent::setName($name);
        $this->getView()->validateDojoForm($this->getName());
        return $this;
    }
}

All this does is call our validateDojoForm helper and pass it the id of the form we create. Now we create all our Dojo forms by extending our custom class:

class Form_Name extends My_Dojo_Form
{
    public function init()
    {
        $this->setName('myForm');
 
        $this->addElement('ValidationTextBox', 'name', array(
            'validators' => array(
                array('StringLength', false, array(0, 255)),
            ),
            'label'          => 'Name',
            'required'       => true,
            'invalidMessage' => 'Please type your name.',
            'trim'      => true,
        ));
 
 
        $this->addElement('SubmitButton', 'submitButton',
            array(
                'required'   => false,
                'ignore'     => true,
                'label'      => 'Save'
            )
        );
    }
}

Be sure to call setName() when creating your form. This will call our validateDojoForm helper and pass it the id of the form we create and thus capturing the neccessary javascript to validate our form when it’s submitted.

enjoy!

Comments | RSS

#1
Michael B said

You’re a god send!!!

#2
Tom G said

Worked well, thanks! Shame it is needed.

#3
Daniel Holmes said

Thank you! Thank you!

I’m still pretty new (a month or so of dabbling) with Zend_Form and Dojo, but it looks like in 1.1.10 (at least) I needed to do a little blending between you and Matthew. I love your idea of making it a view helper and showing me how, but registering everything at the top was loading it before Zend_Form had setup Dojo.

So, My ValidateDojoForm in the view helper looks more like so:


public function ValidateDojoForm($formId)
{
$this->view->dojo()->javascriptCaptureStart(); ?>
function validateForm() {
var form = dijit.byId("");
if (!form.validate()) {
return false;
}
return true;
}
view->dojo()->javascriptCaptureEnd();?>
view->dojo()->onLoadCaptureStart(); ?>
function() {
dojo.connect(dijit.byId(""), "onSubmit", "validateForm");
}

view->dojo()->onLoadCaptureEnd();
}

Just thought I would throw that on there for the next newbie who comes along.

Again, your post really helped me to get a little closer to “getting it.” Thanks!

#4
chrismacp said

Very useful, cheers :)

#5
Marcos said

I do this on form:

$this->setAttribs(array(
‘method’ => ‘post’,
‘name’ => ‘form’,
‘onSubmit’ => ‘return this.validate();’
));

#6
Leon Myburgh said

Thanks. This worked perfectly for what I had in mind. The Custom Zend Dojo Form Class method helped me add this to all my forms in a matter of minutes. Saved me from having to solve it myself.

#7
Hoang Nguyen said

Great, this really helps me out

#8
Santiago said

Marcos!! Your code works fine and triggers all the errors already set in the form!! great!!

Leave a Reply