В Yii есть ли способ проверки табличного ввода с помощью CActiveForm? - PullRequest
4 голосов
/ 06 марта 2012

Положение

Я использовал вики-статью на сайте Yii, Сбор табличных данных , чтобы следовать в качестве примера.

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

Я импортирую CSV-файлы, в которых заголовки разных файлов различаются. Перед правильным анализом файлов пользователь должен сопоставить, какой заголовок будет сопоставлен с какой таблицей / столбцом.

У меня есть одна модель, ImportParseForm расширенная с CFormModel. Это действительно только одно правило:

public function rules()
{
    return array(
        array('header', 'required'),
    );
}

Вот фрагмент моего взгляда:

<?php foreach($headers as $h => $hItem): ?>    
<div class="row">
    <?php echo CHtml::label(CHtml::encode($hItem), "[$h]header"); ?> maps to
    <?php echo $fParse->textField($mForm, "[$h]header"); ?>
    <?php echo $fParse->error($mForm, "[$h]header"); ?>
</div>
<?php endforeach; ?>

Вот фрагмент моего контроллера:

        $mForm = new ImportParseForm;
        $valid = true;

        if (isset($_POST['ImportParseForm'])){
            foreach ($headers as $h => $hVal){
                if (isset($_POST['ImportParseForm'][$h])){
                    $mForm->attributes = $_POST['ImportParseForm'][$h];
                    $valid = $mForm->validate() && $valid;
                }
            }


            if ($valid){
                // Process CSV
            }
        }

Если все поля действительны, то они проходят, как и ожидалось. Проблема в том, что если одно из полей недопустимо (или в данном случае пусто), тогда все поля помечаются как недействительные.

В Yii 1.1.10 они добавили CActiveForm :: validateTabular () , но похоже, что это для нескольких моделей. Не совсем то, что у меня здесь. Но для удовольствия я добавил следующее к своему контроллеру (конечно, удалил другой тип проверки):

CActiveForm::validateTabular($mForm, array('header'));

Сама форма действительна, только если заполнен первый элемент. Если первый элемент заполнен, он установит все остальные элементы с тем же значением (и пройдет проверку).

Вопрос

Можно ли использовать CActiveForm для проверки по полям, которые генерируются динамически (аналогично табличному вводу, но только с одной моделью)?

Ответы [ 2 ]

1 голос
/ 09 мая 2012

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

смотреть код:

    <?php foreach($modelArray as $model): ?>
        <div class="row">
                <?php echo $form->textField($model, "[$model->id]attributeName"); ?>
                <?php echo $form->label($model, "[$model->id]attributeName"); ?>
                <?php echo $form->error($model, "[$model->id]attributeName"); ?>
        </div>
    <?php endforeach; ?>

код контроллера:

    objArray = array();
    foreach($_REQUEST['ModelName'] as $id => $attributes){
        $obj = ModelName::model()->findByPk($id);
        $obj->attributes = $attributes;
        $obj->save();
        $objArray[$id] = $obj;
    }
    echo CActiveForm::ValidateTabular($objArray);
    Yii::app()->end(); 
0 голосов
/ 08 марта 2012

После прочтения Сбор табличного ввода чуть ближе, я использую "несколько" моделей. Я неправильно понял, что множественные модели означают множество различных структурированных моделей, а не просто несколько одинаковых структурированных моделей в массиве. Например, в вики есть фрагмент, который показывает, какие элементы (массив моделей) нужно обновить: $items=$this->getItemsToUpdate();. Мое исправленное предположение состоит в том, что этот конкретный метод захватывает несколько одинаковых структурированных моделей, но с разными первичными ключами ... или разными записями. Понимая это, остальная часть статьи имеет больше смысла;)

Но вот мое модельное решение о том, как создать форму отображения заголовка CSV.

class ImportParseForm extends CFormModel{

    // Model really only has one attribute to check against, the header
    var $header;
    // New attributeLabels collected and stored on class instantiation
    protected $attributeLabels;

    // Modify construct so we can pass in custom attribute labels
    public function __construct($attributeLabels = '', $scenario = '')
    {
        if (! is_array($attributeLabels)){
            $this->attributeLabels = array($attributeLabels);
        }
        else{
            $this->attributeLabels = $attributeLabels;
        }

        parent::__construct($scenario);
    }


    public function rules()
    {
        return array(
            array('header', 'required'),
        );
    }

    public function attributeLabels()
    {
        // Default mapping
        $arr = array(
            'header' => 'Header Mapping',
        );

        // Merge mapping where custom labels overwrite default
        return array_merge($arr, $this->attributeLabels);
    }
}

Вот фрагмент кода в моем контроллере, на котором мой эквивалент $items=$this->getItemsToUpdate(); (опять же, цель состоит в том, чтобы собрать массив моделей) выглядел бы как

        // Get the first row of CSV, assume it's the headers
        $tmpCsvRow = explode("\n", $mTmp->data);
        $headers = explode(',', $tmpCsvRow[0]);

        foreach ($headers as $header){
            if (! empty($header)){ // Blank headers are lame, skip them
                // Add a new model for each CSV header found into $mForm array
                // You can also add in a custom attributeLabel, $header is an actual header name like 'First Name',
                // so the new label for the header attribute in ImportParseForm would be 'First Name header' and
                // it will show up properly in your CActiveForm view
                $mForm[] = new ImportParseForm(array('header' => $header.' header'));
            }
        }

Нажмите $mForm на ваш взгляд. Теперь, по вашему мнению, выполните итерацию по $mForm для вашей формы следующим образом (аналогично статье в вики, но здесь я использую виджет CActiveForm):

<?php foreach($mForm as $m => $mItem): ?>
<div class="row">
    <?php echo $fParse->labelEx($mItem,"[$m]header"); ?> maps to
    <?php echo $fParse->textField($mItem, "[$m]header"); ?>
    <?php echo $fParse->error($mItem, "[$m]header"); ?>
</div>
<?php endforeach; ?>

Проверка работает как ожидалось.

Если вы хотите использовать проверку AJAX, используйте CActiveForm::validateTabular() в вашем контроллере (вместо обычного validate()).

Надеюсь, это поможет другим начинающим Yii! :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...