选择选项中的zend表单自定义属性?

时间:2011-03-23 06:01:35

标签: php zend-framework zend-form

我想知道如何在Zend表单的选择字段中为选项添加自定义属性。

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>

如何在选项中添加此类型属性?

6 个答案:

答案 0 :(得分:10)

使用ZF的Zend_Form_Element_Select实现是不可能的。您需要创建自己的元素。我做了类似的事情,这是相关的代码:

<?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;
    }
}

将此放入/library/Zend/Form/Element/SelectAttribs.php。您还需要一个帮助器来渲染元素。将它放入您的视图助手目录中,并将其命名为SelectAttribs.php。这是我的文件的内容:

<?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>";
    }
}

有了这个,你应该准备好了:

$elt = new Zend_Form_Element_SelectAttribs('whatever');
$elt->addOption($value,$label,array('attribname' => 'attribvalue'));

答案 1 :(得分:3)

使用addMultiOption($ value,$ label)我只需将value参数设置为:

$value = $id . '" ref="' . $ref;

当它呈现时:

<option value="<idValue>" ref="<refValue"><labelValue></option>

希望这会有所帮助......

好的,值被转义,但是optionClasses在添加addMultiOptions(val,lable)的循环中没有这样做我做了这样的事情:

$optionClasses[<val>] = 'ref_' . <val> . '" ref="' . <ref>;

然后在循环之后只做一个setAttrib('optionClasses',$ optionClasses)

这实际上有效......

我为另一个问题回答了这个问题,但是找不到在这里添加评论的方法来引用它;那是Zend Framework addMultiOption adding custom parameters like "rel" for options

答案 2 :(得分:2)

我没有发现@ mingos的答案已完成,并且在实现设置值方面存在一些问题。他的答案对需要扩展和改变的内容有很大帮助。一旦我有了这个开始,其余的很容易。我只是扩展了ZF1的Select并覆盖了我需要的位置:

/**
 * 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);
    }
}

视图助手:

类MyNamespace_View_Helper_SelectAttribs扩展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;
}

}

表单中的实现类似于:

$selectElement = new MyNamespace_Form_Element_SelectAttribs('selectElementName');
$selectElement->addMultiOption($value, $label, array('data-custom' => 'custom data embedded in option tag.');

我希望能有所帮助。感谢。

答案 3 :(得分:1)

migos, 你忘记了多重选择的setvalue方法。

你应该添加如下内容:

...
foreach ($options as $opt_value => $option) {
            $opt_disable = '';
            $opt_selected = '';
            if (is_array($disable) && in_array($opt_value, $disable)) {
                $opt_disable = ' disabled="disabled"';
            }
            if (in_array($opt_value,$value)) {
                $opt_selected = ' selected="selected"';
            }
            $list[] = $this->_build($option, $disabled, $opt_selected);
        }
...
and

protected function _build($option, $disabled, $opt_selected) {
        $html = '<option';
        foreach ($option as $attrib => $value) {
            $html .= " $attrib=\"$value\"";
        }
        return $html . $disabled . $opt_selected . " foo>" . $option['label'] . "</option>";
    }

答案 4 :(得分:0)

你可以扩展/覆盖Zend_View_Helper_FormSelect助手,但真正的问题是将额外的数据带入每个选项。

默认情况下,Zend_Form_Element_Select(通过Zend_Form_Element_Multi)要求每个选项有两个字符串,一个用于value属性,另一个用于文本内容。您可能需要创建自己的元素来处理额外的数据。

答案 5 :(得分:0)

根本不需要自定义表单元素,你可以做的是: $ element-&gt; setAttrib('disable',array(1,2,5));

http://pietervogelaar.nl/set-attribute-on-select-option-with-zend_form/

所述