phpzend-frameworkzend-form

zend-form select optgroup, how to specify id


Hello i am using Zend Framework Form and have tried to get this example to work http://framework.zend.com/issues/browse/ZF-8252, but it fails xD

this is my code

$options = Array
(
    [] => Qualsiasi Agente
    [agenti_attivi] => Array
        (
            [4] => Giovanni Abc
            [10] => Luigi Abc
            [13] => Michela Abc
        )

);

$agenti->addMultiOptions($options);

and the generated code is :

<select name="agente_id" id="agente_id" tabindex="6">
    <option value="" label="Qualsiasi Agente" selected="selected">Qualsiasi Agente</option>
    <optgroup id="agente_id-optgroup-Agenti attivi: " label="Agenti attivi: ">
    <option value="4" label="Giovanni Abc">Giovanni Abc</option>
    <option value="10" label="Luigi Capoarea">Luigi Abc</option>
    <option value="13" label="Michela Abc">Michela Abc</option>
    </optgroup>

</select>

where id="agente_id-optgroup-Agenti attivi: " is not xhtml valid Line 724, Column 44: value of attribute "id" must be a single token

i am using zend 1.11.10

thanks


Solution

  • Create a custom view helper FormSelect that extends the core FormSelect and then modify the code.

    1. Include the path to your view helpers in the bootstrap file

    protected function _initHelpers()
    {
        $this->bootstrap('view');
        $view = $this->getResource('view');
        $view->addHelperPath('My/View/Helper', 'My_View_Helper');
    }
    
    1. The custom view helper. It's a copy of Zend_View_Helper_FormSelect but with small modification.

      class My_View_Helper_FormSelect extends Zend_View_Helper_FormSelect {

      public function formSelect($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 $opt_value => $opt_label) {
              if (is_array($opt_label)) {
                  $opt_disable = '';
                  if (is_array($disable) && in_array($opt_value, $disable)) {
                      $opt_disable = ' disabled="disabled"';
                  }
                  if (null !== $translator) {
                      $opt_value = $translator->translate($opt_value);
                  }
                  $opt_id = ' id="' . $this->formatElementId($id . '-optgroup-' . $opt_value) . '"';
                  $list[] = '<optgroup'
                          . $opt_disable
                          . $opt_id
                          . ' label="' . $this->view->escape($opt_value) .'">';
                  foreach ($opt_label as $val => $lab) {
                      $list[] = $this->_build($val, $lab, $value, $disable);
                  }
                  $list[] = '</optgroup>';
              } else {
                  $list[] = $this->_build($opt_value, $opt_label, $value, $disable);
              }
          }
      
          // add the options to the xhtml and close the select
          $xhtml .= implode("\n    ", $list) . "\n</select>";
      
          return $xhtml;
      }
      
      private function formatElementId($id)
      {
          // in here put whatever filter you want for the id value
          $id = trim(strtr($id, array('[' => '-', ']' => '', ' ' => '', ':' => '')), '-');
          $id = strtolower($id);
          return $id;
      }
      

      }

    Done. Create multi select element with a valid id.

    <?php
    $this->addElement('multiSelect', 'agente_id', array(
        'label' => 'Label Name:',
        'multiOptions' => array(
            '' => 'Qualsiasi Agente',
            'Agenti attivi: ' => array(
                4 => 'Giovanni Verdi',
                10 => 'Luigi Capoarea',
                13 => 'Michela Passarin',
            )
        )
    ));