I am using zend_form (part of Zend Framwork) to create a form and found when I add a set of checkboxes using Zend_Form's multicheckbox element (Zend_Form_Element_MultiCheckbox) the code that is outputted like so:
<label for="subjects-maths">
<input type="checkbox" value="maths" id="subjects-maths" name="subjects[]">
Maths
</label>
<label for="subjects-english">
<input type="checkbox" value="maths" id="subjects-english" name="subjects[]">
English
</label>
I.e. the input is inside the label. Whereas the code is technically ok it is against good practice as far as the W3c see it and is also not the way I want it as it makes styling harder. What I want is the following:
<div>
<label for="subjects-maths">
Maths
</label>
<input type="checkbox" value="maths" id="subjects-maths" name="subjects[]">
</div>
<div>
<label for="subjects-english">
English
</label>
<input type="checkbox" value="maths" id="subjects-english" name="subjects[]">
</div>
Therefore how do I move the checkbox input out of the label and how do I surround each option in divs. I have looked at many pages on the internet of so called solutions but none work on multicheckboxes as it only targets surrounding labels (i.e the one that would say subjects in this example) not the actual options labels and inputs.
Please help.
Thanks
Paul
The decorator Zend_Form_Decorator_ViewHelper
is by default using the view helper Zend_View_Helper_FormMultiCheckbox
to render your multicheckbox element. That view helper is extended from Zend_View_Helper_FormRadio
which for some reason is hard-coded to put <label>
tags around the <input>
tag.
You'll need to write your own view helper that copies most of the code from Zend_View_Helper_FormRadio::formRadio()
but writes the HTML without <label>
tags around the element. Here's a snippet from another answer that shows the modification you might want to make.
Your custom helper should be named Some_Prefix_Helper_FormMultiCheckbox
but
without knowing how your app is structured it's hard to say exactly what that Some_Prefix
should be or how you would make sure to load it instead of Zend_View_Helper_FormMultiCheckbox
. Check out the documentation on loading plugins for some tips.
It appears the best solution is based on the answer above by squirrel. As the input being inside a label is hard coded the best solution is to change this behavour. You can either do this by modifying the Zend_View_Helper_FormRadio class or override it with your own custom view header. I would recommend the custom header option as modifying the zend framework would be a bad idea as it would need updating everytime you updated the framework, have an effect on anyone or any project using that copy of the framework etc. By using a custom helper it will be specific to the project and it will not affect anything else nor will it be affected by updating the framework (however you may find you need to update the helper if the framework update has changed some behaviours). What I did which is working well is:
1 - Created a model/module in the library, I called mine website. This first involves creating a folder in the library the same name as the model. Thus I have library > website
Edit: Forgot to say you will need to register the plugin library either via the bootstrap or application.ini. I find it is easiest just add:
autoloaderNamespaces[] = "Website_"
Anywhere below appnamespace
2 - I created the relevant subfolders and file for the class Website_View_Helper_FormRadio which will override Zend_View_Helper_FormRadio. Thus the folder and file stucture is
website > view > helper > FormRadio.php
3 - I then copied the contents of the formRadio function from Zend_View_Helper_FormRadio into Website_View_Helper_FormRadio within the class. I then modified it with the code that squirrel referred thus the Website_View_Helper_FormRadio class that inherits from Zend_View_Helper_FormRadio like so:
class Website_View_Helper_FormRadio extends Zend_View_Helper_FormRadio
{
public function formRadio($name, $value = null, $attribs = null, $options = null, $listsep = "<br />\n")
{
// The code from the formRadio function in Zend_View_Helper_FormRadio with
// the modification from the code squirrel referred to
}
}
This then gives us our own copy of the class with our modified code that inherits from the zend version of the FormRadio element.
You can now just use the Zend Form Radio element like normal and it will use our improvements
Note if you wish to have the same effect on MultiCheckbox or checkbox you need to make these use our version of form radio as these elements use form radio as a basis. To do this we create our own versions of these in our library and make them inherit from our version. We would therefore have for multicheckbox the following:
library > website > view > helper > FormMultiCheckbox.php
Would be a copy of Zend_View_Helper_FormMultiCheckbox
Then replace the line:
class Zend_View_Helper_FormMultiCheckbox extends Zend_View_Helper_FormRadio
with:
class Website_View_Helper_FormMultiCheckbox extends Website_View_Helper_FormRadio
I hope that helps someone.
Here are some additionnal information about multiCheckBox rendering customization
I wanted the checkboxes' labels to prepend instead of append (this default behaviour is hardcoded). As the ZF reference guide isn't talkative about it, I finally got into the core code to figure out how to customize it. Have a look to Zend_View_Helper_FormRadio::formRadio()
for more info.
It's possible to modify the checkboxes decorator via the multiCheckBox options : adding some options prefixed with label_
.
Here is my form element :
$this->addElement('multiCheckbox', 'stars_number', array(
'filters' => array('Int'),
'escape' => false, // to allow html in the labels
'separator' => '', // to keep everything inline
'label_placement' => 'prepend',
'label_class' => 'stars', // custom css needed
'decorators' => $decorator_chain, // decorators array defined upper, and passed to many elements of the form
));
I hope this will help some to save hours of unsuccessful google crawling...
I think you need remove decorator Label and create own decorator which will work like Label decorator but use div and label tags together as you need