0

CActiveForm::dropdownList()在很多很多地方使用。为了加快开发速度,我想编写一个封装所有相关工作的小部件。我有一些可以正确显示但失去CActiveForm.

这是我直接创建下拉列表的方法。$activeModel指的是使用的模型(CActiveRecordCActiveForm$allItems是一个CActiveRecord用于填充下拉列表的数组。此代码完美运行。

<div class="row">
    <?php echo $form->labelEx($activeModel, 'keyId'); ?>:
    <?php
    $data = array();
    foreach ($allItems as $Item) {
        $data[$Item->keyId] = CHtml::encode($Item->keyName);
    }
    $options = array(
        'prompt' => 'Select an item',
        'options' => array($activeModel->keyId => array('selected' => true)),
    );
    echo $form->dropDownList($activeModel, 'keyId', $data, $options);
    ?>
    <?php echo $form->error($activeModel, 'keyId'); ?>
</div>

从理论上讲,小部件的包含方式CActiveForm如下:

<div class="row">
    <?php echo $form->labelEx($activeModel, 'keyId'); ?>
    <?php $this->widget('path.to.CustomDropdown', array(
        'form' => $form,
        'items' => $allItems,
        'model' => $activeModel,
        'prompt' => 'Select an item',
        'selected' => true,
    )); ?>
    <?php echo $form->error($activeModel, 'keyId'); ?>
</div>

小部件本身如下所示:

<?php
/**
 * Echoes a populated <select> element
 */
class CustomDropdown extends CWidget {
    public $form;
    public $items = array();
    public $model;
    public $prompt;
    public $selected = false;

    /**
     * @var CActiveForm $form
     * @var CActiveRecord[] $items
     * @var CActiveRecord $model
     * @var string $prompt
     * @var bool $selected (optional)
     */
    public function run() {
        $data = array();
        foreach ($this->items as $Item) {
            $data[$Item->{$Item->tableSchema->primaryKey}] = CHtml::encode($Item->getName());
        }

        $options = array(
            'prompt' => CHtml::encode($this->prompt),
            'options' => (
                $this->selected ? array($this->model->{$Item->tableSchema->primaryKey} => array('selected' => true)) : array()
            ),
        );

        echo $this->form->dropDownList($this->model, $this->model->tableSchema->primaryKey, $data, $options);
    }
}
?>

所有这些都有效,但CActiveForm在下拉列表中失去了验证功能。具体来说,小部件$form没有映射到 CActiveForm 的验证数组,因此永远不会向用户显示提交错误。

如何完全集成这种类型的小部件,CActiveForm以免丢失任何功能?谢谢您的帮助。

4

1 回答 1

0

从您的示例来看,调用小部件会导致编写比$form->dropDownList()调用更多的代码。我建议简化一些代码并继续使用无小部件解决方案。

为什么需要此代码?

$data = array();
foreach ($allItems as $Item) {
    $data[$Item->keyId] = CHtml::encode($Item->keyName);
}
$options = array(
    'prompt' => 'Select an item',
    'options' => array($activeModel->keyId => array('selected' => true)),
);

你只是在重复做什么CHtml::listData()。您可以像这样简单地创建下拉菜单:

echo $form->dropDownList(
    $activeModel,
    'keyId',
    CHtml::listData( MyActiveRecordForDropDown::model()->findAll(), 'valueField', 'textField' ),
    array( 'prompt' => 'Select an item' )
);

并且所选项目将由模型属性值自动选择。

于 2014-12-06T10:42:05.867 回答