Zend Framework Вложенные флажки - PullRequest
       14

Zend Framework Вложенные флажки

5 голосов
/ 20 октября 2010

Я хотел бы создать Zend_Form с вложенными флажками. Я уверен, что это возможно, но я не помню, как это сделать. Вот как это будет выглядеть:

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

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

Как бы я достиг этого результата?

Ответы [ 2 ]

1 голос
/ 26 марта 2011

У меня есть одно решение этой проблемы. Это не самое лучшее, но мне этого достаточно.

сначала вам нужен правильный массив, который вы передадите в форму. если вы выбираете данные из базы данных, ваш массив будет иметь аналогичную структуру:

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
    )
)

Вам необходимо преобразовать этот массив. Я использовал фильтр для него:

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

Что делает этот фильтр? он возвращает отсортированный одномерный массив относительно родительского элемента. Вложенный уровень помечается как «---». Пример:

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'
)

Тогда я создаю форму. У него есть определенный элемент category_id. Я установлю для него помощник вида.

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

Тогда вам нужно просмотреть код помощника:

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

Этот помощник найдет метку '---' и установит три проставки (&nbsp;) перед флажком.

Так что оставайтесь, просто покажите действие контроллера. Вы получаете список категорий из базы данных, фильтруете его в новом массиве, затем создаете форму и отправляете в форму отфильтрованного массива:

$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;
0 голосов
/ 18 января 2011

Вы можете использовать ViewScript Decorator, чтобы сделать это

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

Пример

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')
                    )
            )
        ));
    }
}

Создать _element.phtml в вашем представлениикаталог скриптов.

<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>
...