I want know how to add custom attribute for option in a select field of Zend form.
PHP:
$option_values = array("multiOptions" => array(
"US" => "United States",
"CA" => "Canada",
));
$type=array('big','small');
$option= new Zend_Form_Element_Select('option', $option_values);
HTML:
<select>
<option value='US' type='big'>United States</option>
<option value='CA' type='small'>Canada</option>
</select>
How to add this type attribute in the option?
It is not possible using ZF's implementation of Zend_Form_Element_Select
. You need to create your own element. I have done something similar, here's the relevant code:
<?php
require_once 'Zend/Form/Element/Select.php';
/**
* Select, but with the possibility to add attributes to <option>s
* @author Dominik Marczuk
*/
class Zend_Form_Element_SelectAttribs extends Zend_Form_Element {
public $options = array();
public $helper = 'selectAttribs';
/**
* Adds a new <option>
* @param string $value value (key) used internally
* @param string $label label that is shown to the user
* @param array $attribs additional attributes
*/
public function addOption ($value,$label = '',$attribs = array()) {
$value = (string) $value;
if (!empty($label)) $label = (string) $label;
else $label = $value;
$this->options[$value] = array(
'value' => $value,
'label' => $label
) + $attribs;
return $this;
}
}
Put this into /library/Zend/Form/Element/SelectAttribs.php. You also need a helper to render the element. Put it into your view helpers directory, name it SelectAttribs.php as well. Here's the contents of my file:
<?php
require_once 'Zend/View/Helper/FormElement.php';
class Zend_View_Helper_SelectAttribs extends Zend_View_Helper_FormElement {
public function selectAttribs($name, $value = null, $attribs = null, $options = null, $listsep = "<br />\n") {
$info = $this->_getInfo($name, $value, $attribs, $options, $listsep);
extract($info); // name, id, value, attribs, options, listsep, disable
// force $value to array so we can compare multiple values to multiple
// options; also ensure it's a string for comparison purposes.
$value = array_map('strval', (array) $value);
// now start building the XHTML.
$disabled = '';
if (true === $disable) {
$disabled = ' disabled="disabled"';
}
// Build the surrounding select element first.
$xhtml = '<select'
. ' name="' . $this->view->escape($name) . '"'
. ' id="' . $this->view->escape($id) . '"'
. $disabled
. $this->_htmlAttribs($attribs)
. ">\n ";
// build the list of options
$list = array();
$translator = $this->getTranslator();
foreach ($options as $opt_value => $option) {
$opt_disable = '';
if (is_array($disable) && in_array($opt_value, $disable)) {
$opt_disable = ' disabled="disabled"';
}
$list[] = $this->_build($option, $disabled);
}
// add the options to the xhtml and close the select
$xhtml .= implode("\n ", $list) . "\n</select>";
return $xhtml;
}
protected function _build($option, $disabled) {
$html = '<option';
foreach ($option as $attrib => $value) {
$html .= " $attrib=\"$value\"";
}
return $html.$disabled.">".$option['label']."</option>";
}
}
With this, you should be ready to go:
$elt = new Zend_Form_Element_SelectAttribs('whatever');
$elt->addOption($value,$label,array('attribname' => 'attribvalue'));
Using addMultiOption($value,$label) I just set the value parameter to something like:
$value = $id . '" ref="' . $ref;
and when it renders you get:
<option value="<idValue>" ref="<refValue"><labelValue></option>
Hope this helps....
Okay, value gets escaped but optionClasses does not so inside the loop that adds the addMultiOptions(val,lable) I do something like this:
$optionClasses[<val>] = 'ref_' . <val> . '" ref="' . <ref>;
and then after the loop just do a setAttrib('optionClasses',$optionClasses)
And that actually works...
I answered this for another question but could not find a way to add a comment here to reference it; It was Zend Framework addMultiOption adding custom parameters like "rel" for options
I didn't find @mingos's answer complete and had some issues with implementing setting the value. His answer helped a lot with what needed to be extended and changed however. Once I had that start the rest was pretty easy. I just extended ZF1's Select and overrode where I needed:
/**
* Select, now with abbility to specify attributes on <Option>, addMultiOption has new syntax
* @author Seth Miller
*/
class MyNamespace_Form_Element_SelectAttribs extends Zend_Form_Element_Select {
public $options = array();
public $helper = 'selectAttribs';
/**
* Add an option
*
* @param string $option
* @param string $value
* @return Zend_Form_Element_Multi
*/
public function addMultiOption($value, $label = '', $attribs = array()) {
$value = (string) $value;
if (!empty($label)) {
$label = (string) $label;
}
else {
$label = $value;
}
$this->_getMultiOptions();
if (!$this->_translateOption($value, $label)) {
$this->options[$value] = array(
'value' => $value,
'label' => $label
) + $attribs;
}
return $this;
}
/**
* Add many options at once
*
* @param array $options
* @return Zend_Form_Element_Multi
*/
public function addMultiOptions(array $options) {
foreach ($options as $optionKey => $optionProperties) {
if (is_array($optionProperties)
&& array_key_exists('key', $optionProperties)
&& array_key_exists('value', $optionProperties)
) {
if(array_key_exists('key', $optionProperties)) $optionKey = $optionProperties['key'];
$this->addMultiOption($optionKey, $optionProperties['value'], $optionProperties['attribs']);
}
else {
$this->addMultiOption($optionKey, $optionProperties);
}
}
return $this;
}
public function isValid($value, $context = null)
{
if ($this->registerInArrayValidator()) {
if (!$this->getValidator('InArray')) {
$multiOptions = $this->getMultiOptions();
$options = array();
foreach ($multiOptions as $optionKey => $optionData) {
// optgroup instead of option label
if (is_array($optionData['options'])) {
$options = array_merge($options, array_keys($optionData['options']));
}
else {
$options[] = $optionKey;
}
}
$this->addValidator(
'InArray',
true,
array($options)
);
}
}
return parent::isValid($value, $context);
}
}
And the view helper:
class MyNamespace_View_Helper_SelectAttribs extends Zend_View_Helper_FormElement {
public function selectAttribs($name, $value = null, $attribs = null, $options = null, $listsep = "<br />\n") {
$info = $this->_getInfo($name, $value, $attribs, $options, $listsep);
extract($info); // name, id, value, attribs, options, listsep, disable
// force $value to array so we can compare multiple values to multiple
// options; also ensure it's a string for comparison purposes.
$value = array_map('strval', (array) $value);
// check if element may have multiple values
$multiple = '';
if (substr($name, -2) == '[]') {
// multiple implied by the name
$multiple = ' multiple="multiple"';
}
if (isset($attribs['multiple'])) {
// Attribute set
if ($attribs['multiple']) {
// True attribute; set multiple attribute
$multiple = ' multiple="multiple"';
// Make sure name indicates multiple values are allowed
if (!empty($multiple) && (substr($name, -2) != '[]')) {
$name .= '[]';
}
}
else {
// False attribute; ensure attribute not set
$multiple = '';
}
unset($attribs['multiple']);
}
// now start building the XHTML.
$disabled = '';
if (true === $disable) {
$disabled = ' disabled="disabled"';
}
// Build the surrounding select element first.
$xhtml = '<select'
.' name="'.$this->view->escape($name).'"'
.' id="'.$this->view->escape($id).'"'
.$multiple
.$disabled
.$this->_htmlAttribs($attribs)
.">\n ";
// build the list of options
$list = array();
$translator = $this->getTranslator();
foreach ((array) $options as $optionKey => $optionData) {
if (isset($optionData['options'])) {
$optDisable = '';
if (is_array($disable) && in_array($optionData['value'], $disable)) {
$optDisable = ' disabled="disabled"';
}
if (null !== $translator) {
$optValue = $translator->translate($optionData['value']);
}
$optId = ' id="'.$this->view->escape($id).'-optgroup-'
.$this->view->escape($optionData['value']).'"';
$list[] = '<optgroup'
.$optDisable
.$optId
.' label="'.$this->view->escape($optionData['value']).'">';
foreach ($optionData['options'] as $optionKey2 => $optionData2) {
$list[] = $this->_build($optionKey2, $optionData2, $value, $disable);
}
$list[] = '</optgroup>';
}
else {
$list[] = $this->_build($optionKey, $optionData, $value, $disable);
}
}
// add the options to the xhtml and close the select
$xhtml .= implode("\n ", $list)."\n</select>";
return $xhtml;
}
/**
* Builds the actual <option> tag
*
* @param string $value Options Value
* @param string $label Options Label
* @param array $selected The option value(s) to mark as 'selected'
* @param array|bool $disable Whether the select is disabled, or individual options are
* @return string Option Tag XHTML
*/
protected function _build($optionKey, $optionData, $selected, $disable)
{
if (is_bool($disable)) {
$disable = array();
}
$opt = '<option';
foreach ($optionData as $attrib => $attribValue) {
$opt .= ' '.$this->view->escape($attrib).'="'.$this->view->escape($attribValue).'"';
}
// selected?
if (in_array((string) $optionData['value'], $selected)) {
$opt .= ' selected="selected"';
}
// disabled?
if (in_array($optionData['value'], $disable)) {
$opt .= ' disabled="disabled"';
}
$opt .= '>' . $this->view->escape($optionData['label']) . "</option>";
return $opt;
}
}
And implementation in a form would be something like:
$selectElement = new MyNamespace_Form_Element_SelectAttribs('selectElementName');
$selectElement->addMultiOption($value, $label, array('data-custom' => 'custom data embedded in option tag.');
I hope that helps someone. Thanks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With