2010-10-19 5 views
5

Je souhaite créer un Zend_Form avec des cases à cocher imbriquées. Je suis sûr que c'est possible, mais je ne me souviens pas comment le faire. Voici à quoi cela ressemblerait:Zend Framework Cases à cocher imbriquées

[x] Top level checkbox 1 
    [ ] Sub level 1 
    [x] Sub level 2 

[ ] Top level 2 
    [ ] Sub level 1 
    [ ] Sub level 2 

Comment pourrais-je obtenir ce résultat?

Répondre

0

Vous pouvez utiliser ViewScript décorateur pour faire

http://framework.zend.com/manual/en/zend.form.standardDecorators.html#zend.form.standardDecorators.viewScript

Exemple

class MyForm extends Zend_Form 
{ 

    public function init() 
    { 
     $this->addElement('checkbox', 'elementName', array(
      'multiOptions' => array(
       'level1' => array(
        'Level 1 Option 1', 
        'Level 1 Option 2', 
       ), 
       'level2' => array(
        'Level 2 Option 1', 
        'Level 2 Option 2', 
       ), 
      ), 
      'label' => 'Element Label', 
      'decorators' => array(
       array('ViewScript', array(
         'viewScript' => '_element.phtml', 
         'class' => 'form element') 
        ) 
      ) 
     )); 
    } 
} 

Créer _element.phtml dans votre répertoire de script de vue.

<div class="<?php echo $this->class ?>"> 
    <?php echo $this->formLabel($this->element->getName(), 
         $this->element->getLabel()) ?> 

    <?php $options = $this->element->getAttribs(); ?> 

    <?php if(isset($options['multiOptions']) && is_array($options['multiOptions'])): ?> 
     <ul> 
     <?php foreach($options['multiOptions'] as $level => $levelOptions): ?> 
      <li> 
       <span><?php echo $level; ?></span> 
       <?php if(is_array($levelOptions)): ?> 
       <ul> 
        <?php foreach($levelOptions as $key => $value): ?> 
        <li> 
         <?php echo $this->{$this->element->helper}(
          $this->element->getName() . '[' . $key . ']', 
          $this->element->getValue(), 
          $options['options'] 
         ) ?><label><?php echo $value; ?></label> 
        </li> 
        <?php endforeach; ?> 
       </ul> 
       <?php endif; ?> 
      </li> 
     <?php endforeach; ?> 
     </ul> 
    <?php endif; ?> 

    <?php echo $this->formErrors($this->element->getMessages()) ?> 

    <div class="hint"><?php echo $this->element->getDescription() ?></div> 
</div> 
1

J'ai une solution à ce problème. Ce n'est pas le meilleur, mais cela me suffit maintenant.

en premier vous avez besoin d'un tableau valide que vous passerez pour former. si vous sélectionnez les données de base de données, votre tableau aura une structure similaire:

array(
0=>array(
    'id'=>1, 
    'name'=>'Top level 1', 
    'parent_id'=>0 
    ) 
1=>array(
    'id'=>2, 
    'name'=>'Top level 2', 
    'parent_id'=>0 
    ) 
2=>array(
    'id'=>3, 
    'name'=>'Sub level 1', 
    'parent_id'=>1 
    ) 
3=>array(
    'id'=>4, 
    'name'=>'Sub level 2', 
    'parent_id'=>1 
    ) 
4=>array(
    'id'=>5, 
    'name'=>'Sub level 1', 
    'parent_id'=>2 
    ) 
5=>array(
    'id'=>6, 
    'name'=>'Sub level 1', 
    'parent_id'=>2 
    ) 
) 

Vous devez transformer ce tableau. J'ai utilisé le filtre pour cela:

class My_Filter_Array_ParentRelation implements Zend_Filter_Interface { 


public function __construct() { 
} 

public function filter($arr) { 
    $data = array(); 
    foreach ($arr as $value) { 
     $data[$value['parent_id']][$value['id']] = $value['name']; 
    } 
    $data = $this->create($data, 0,0); 

    return $data; 
} 

public function create($data, $pid=0,$l) { 
    $new_data = array(); 
    if ($data[$pid]) { 
     foreach ($data[$pid] as $id => $value) { 
      $new_data[$id] = str_repeat('---',$l).$value; 
      if(isset($id)) { 
       $temp_data = $this->create($data, $id,$l+1); 
       $new_data = $new_data + $temp_data; 
      } 
     } 
    } 

    return $new_data; 
} 
} 

Que fait ce filtre? retourne un tableau unidimensionnel trié par rapport à l'élément parent. Le niveau imbriqué est marqué comme "---". Exemple:

array(
1=>'Top level 1', 
3=>'---Sub level 1', 
4=>'---Sub level 2', 
2=>'Top level 2', 
5=>'---Sub level 1', 
6=>'---Sub level 2' 
) 

Ensuite, je crée une forme. Il a un élément spécifique category_id. Je vais définir l'aide de vue pour cela.

class My_Form_Product extends Zend_Form { 

protected $_categories = array(); 

public function init() { 
    $this 
     ->addElement('multiCheckbox', 'category_id', array('label' => 'Category:', 'required' => true, 'multiOptions' => $this->getCategories())); 

    $this->category_id->helper = 'MultiCheckbox'; 
} 

public function setCategories($categories = array()) { 
    $this->_categories = $categories; 
    return $this; 
} 

public function getCategories() { 
    return $this->_categories; 
} 
} 

Ensuite, vous devez afficher le code aide:

class My_View_Helper_MultiCheckbox extends Zend_View_Helper_FormElement 
{ 

protected $_inputType = 'checkbox'; 


protected $_isArray = false; 

public function MultiCheckbox($name, $value = null, $attribs = null, 
    $options = null, $listsep = "\n") 
{ 

    $info = $this->_getInfo($name, $value, $attribs, $options, $listsep); 
    extract($info); // name, value, attribs, options, listsep, disable 
    $listsep = "\n"; 

    // retrieve attributes for labels (prefixed with 'label_' or 'label') 
    $label_attribs = array(); 
    foreach ($attribs as $key => $val) { 
     $tmp = false; 
     $keyLen = strlen($key); 
     if ((6 < $keyLen) && (substr($key, 0, 6) == 'label_')) { 
      $tmp = substr($key, 6); 
     } elseif ((5 < $keyLen) && (substr($key, 0, 5) == 'label')) { 
      $tmp = substr($key, 5); 
     } 

     if ($tmp) { 
      // make sure first char is lowercase 
      $tmp[0] = strtolower($tmp[0]); 
      $label_attribs[$tmp] = $val; 
      unset($attribs[$key]); 
     } 
    } 

    $labelPlacement = 'append'; 
    foreach ($label_attribs as $key => $val) { 
     switch (strtolower($key)) { 
      case 'placement': 
       unset($label_attribs[$key]); 
       $val = strtolower($val); 
       if (in_array($val, array('prepend', 'append'))) { 
        $labelPlacement = $val; 
       } 
       break; 
     } 
    } 

    // the radio button values and labels 
    $options = (array) $options; 

    // build the element 
    $xhtml = ''; 
    $list = array(); 

    // should the name affect an array collection? 
    $name = $this->view->escape($name); 
    if ($this->_isArray && ('[]' != substr($name, -2))) { 
     $name .= '[]'; 
    } 

    // ensure value is an array to allow matching multiple times 
    $value = (array) $value; 

    // XHTML or HTML end tag? 
    $endTag = ' />'; 
    if (($this->view instanceof Zend_View_Abstract) && !$this->view->doctype()->isXhtml()) { 
     $endTag= '>'; 
    } 

    // add radio buttons to the list. 
    $filter = new Zend_Filter_Alnum(); 
    foreach ($options as $opt_value => $opt_label) { 

     // Should the label be escaped? 
     if ($escape) { 
      $opt_label = $this->view->escape($opt_label); 
     } 

     // is it disabled? 
     $disabled = ''; 
     if (true === $disable) { 
      $disabled = ' disabled="disabled"'; 
     } elseif (is_array($disable) && in_array($opt_value, $disable)) { 
      $disabled = ' disabled="disabled"'; 
     } 

     // is it checked? 
     $checked = ''; 
     if (in_array($opt_value, $value)) { 
      $checked = ' checked="checked"'; 
     } 

     // generate ID 
     $optId = $id . '-' . $filter->filter($opt_value); 

     // Wrap the radios in labels 
     $wrapper_start = ''; 
     $wrapper_end = '</label><br >'; 
     $level = substr_count($opt_label,'---'); 
     $opt_label = str_replace('---','',$opt_label); 
     $label = '<label '. $this->_htmlAttribs($label_attribs) . ' for="' . $optId . '">' .$opt_label; 
     $radio = (('prepend' == $labelPlacement) ? $label : '') 
       . str_repeat('&nbsp;&nbsp;&nbsp;',$level).'<input type="' . $this->_inputType . '"' 
       . ' name="' . $name . '"' 
       . ' id="' . $optId . '"' 
       . ' value="' . $this->view->escape($opt_value) . '"' 
       . $checked 
       . $disabled 
       . $this->_htmlAttribs($attribs) 
       . $endTag .' ' 
       . (('append' == $labelPlacement) ? $label : ''); 
     $text = $wrapper_start . $radio . $wrapper_end; 

     // add to the array of radio buttons 
     $list[] = $text; 
    } 

    // done! 
    $xhtml .= implode($listsep, $list); 

    return $xhtml; 
} 
} 

Cette aide se trouve la marque '---' et fixé trois entretoises (&nbsp;) avant case à cocher.

Restez donc simplement en action sur le contrôleur d'affichage. Vous obtenez la liste des catégories de db, filtrez-le dans un nouveau tableau, puis créez un formulaire et envoyez-le pour former le tableau filtré:

$categories = Something::getCategories(); 
$filterCategory = new My_Filter_Array_ParentRelation(); 

$form = new Admin_Form_Product(array(
    'name' => 'Form', 
    'categories' => $filterCategory->filter($categories->toArray()), 
)); 

$this->view->form = $form;