我想用嵌套複選框創建一個Zend_Form
。我確信這是可能的,但我不記得如何去做。這就是它的樣子:Zend框架嵌套複選框
[x] Top level checkbox 1
[ ] Sub level 1
[x] Sub level 2
[ ] Top level 2
[ ] Sub level 1
[ ] Sub level 2
我該如何達到這個結果?
我想用嵌套複選框創建一個Zend_Form
。我確信這是可能的,但我不記得如何去做。這就是它的樣子:Zend框架嵌套複選框
[x] Top level checkbox 1
[ ] Sub level 1
[x] Sub level 2
[ ] Top level 2
[ ] Sub level 1
[ ] Sub level 2
我該如何達到這個結果?
您可以使用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>
我有一個解決方案這個問題。這不是最好的,但現在對我來說已經足夠了。
首先你需要有效的數組,你將傳遞給窗體。 如果從數據庫中選擇數據,你的陣列將有類似的結構:
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(' ',$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;
}
}
此助手會發現標記 '---' 和複選框前設定了三個墊片(
)。
因此,只保留顯示控制器的操作。你從數據庫獲得分類表,過濾新數組,然後創建表單併發送以形成過濾數組:
$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;