Yii2: получение данных из представления списка для записи с активной записью

#javascript #activerecord #yii2

#javascript #activerecord #yii2

Вопрос:

Я создаю анкету и пытаюсь записать полученные ответы, я показываю вопросы в a listview , которые получены из одной таблицы (вопрос), и я хочу записать их в другую таблицу (ответ), используя active record . Я пытался добавить активную форму внутри класса ItemView, но кнопка отправки дублируется каждый раз, когда у меня возникает более 1 вопроса, затем я пытаюсь добавить ее за пределы ItemView, и если кнопка отправки появляется только один раз, но я не могу получить данные, перечисленные в ItemView, потому что я не знаюкак отправить поля активной формы для получения данных из itamView, я попытался отправить их с помощью рендеринга ItemView, но он выдает мне ошибку неопределенной переменной.

Вид

 <?php $form = ActiveForm::begin([
'enableClientValidation' => false,
'enableAjaxValidation' => true,]) ?>

<?= ListView::widget([
    'layout' => '<div class="pull-left">{items}</div>',
    'dataProvider' => $dataProvider,
    'itemView' => function ($model, $key, $index, $widget) {
        return $this->render('_answers',[
            'model' => $model, 
            'index' => $index
        ]);
    },
]); ?><div class="form-group">
<?php echo Html::submitButton('<span class="fa fa-plus"></span>'.' '.Yii::t('backend', 'Send') , ['class' => 'btn btn-primary']) ?>
  

Просмотр _answers

 <td width="5%" class="vcenter" rowspan="3">
    <span class="panel-title-address"><label class="control-label">Nr: <?php echo ($index 1); ?></label></span>
</td>
<td width="95%" class="vcenter">
        <div class="form-group field-qquestion-0-title required">
            <label class="control-label" for="qquestion-type_id"><?= Yii::t('backend', 'Question'.' : ')?></label>
        </div>  
        <div class="form-group field-qquestion-0-title required">
            <label class="control-label" for="qquestion-type_id"><?= $model->question ?></label>
        </div>
    <div class="col-md-4">
        <?php echo $form->field($answer, 'answer')->textInput(['maxlength' => true]) ?>
    </div>
</td>
  

я хочу получить id и answer каждого вопроса, чтобы иметь возможность регистрировать их в таблице ответов.

Ответ №1:

Вы получаете ошибку неопределенной переменной, потому что вы не передаете $form переменную из своего основного представления _answers.php . Вы можете передать это следующим образом:

 <?php $form = ActiveForm::begin([
'enableClientValidation' => false,
'enableAjaxValidation' => true,]) ?>

<?= ListView::widget([
    'layout' => '<div class="pull-left">{items}</div>',
    'dataProvider' => $dataProvider,
    'itemView' => function ($model, $key, $index, $widget) use ($form) {
        return $this->render('_answers',[
            'form' => $form,
            'model' => $model, 
            'index' => $index,
        ]);
    },
]); ?><div class="form-group">
<?php echo Html::submitButton('<span class="fa fa-plus"></span>'.' '.Yii::t('backend', 'Send') , ['class' => 'btn btn-primary']) ?>
  

Что касается отправки нескольких ответов с идентификаторами вопросов, вы можете либо использовать способ, упомянутый в ответе vvpanchev, либо добавить скрытое поле с идентификатором вопроса. _answers.php Представление со скрытым полем:

 <td width="5%" class="vcenter" rowspan="3">
    <span class="panel-title-address"><label class="control-label">Nr: <?php echo ($index 1); ?></label></span>
</td>
<td width="95%" class="vcenter">
        <div class="form-group field-qquestion-0-title required">
            <label class="control-label" for="qquestion-type_id"><?= Yii::t('backend', 'Question'.' : ')?></label>
        </div>  
        <div class="form-group field-qquestion-0-title required">
            <label class="control-label" for="qquestion-type_id"><?= $model->question ?></label>
        </div>
    <div class="col-md-4">
        <?php
            //set the question's id to answer model if you haven't done that already
            $answer->question_id = $model->id;
            //output the hidden input with question id
            echo yiihelpersHtml::activeHiddenInput($answer, "[$index]question_id"); 
        ?>
        <?php echo $form->field($answer, "[$index]answer")->textInput(['maxlength' => true]) ?>
    </div>
</td>
  

Если вы используете подход со скрытым полем, то в вашем контроллере вы можете использовать yiibaseModel::loadMultiple() метод для загрузки данных в модели ответов. Вы также можете использовать yiibaseModel::validateMultiple() для проверки. Я предполагаю, что имя для класса модели ответа является Answer .

 $count = count(Yii::$app->request->post('Answer', []));
$answers = [];
for ($i = 0; $i < $count; $i  ) {
    $answers[] = new Answer();
}
if (
    yiibaseModel::loadMultiple($answers, Yii::$app->request->post())
    amp;amp; yiibaseModel::validateMultiple($answers)
) {
    // ... save your answers and/or do other things needed
}
  

Комментарии:

1. спасибо за вашу помощь. Я пробовал ваше решение, но оно сохраняет мне только последнюю запись.

2. Извините, я пропустил, чтобы обернуть Yii::$app->request->post('Answer', []) это в count() вызов функции. Я отредактировал свой ответ, чтобы исправить это. Если ваш код по-прежнему не работает, вам нужно проверить, правильно ли названы поля формы и правильно ли вы сохранили все свои модели из $answers массива.

3. Теперь у меня возникает ошибка при попытке сохранить a checkboxList , если я выбираю 2 варианта, он выдает мне сообщение Answer must be a string , а когда я выбираю 1, он позволяет мне отправлять, но у меня другая ошибка htmlspecialchars() expects parameter 1 to be string, array given

Ответ №2:

Измените свой ввод ответа следующим образом, и у вас будет ввод ответа на каждый вопрос:

 <?php echo $form->field($answer, '['.$model->id.']answer')->textInput(['maxlength' => true]) ?>
  

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

 if(isset($_POST['Answer']) and !empty($_POST['Answer'])){
    foreach($_POST['Answer'] as $question_id => $answer){
        //save your answer to your question
    }
}
  

Вам также нужно будет изменить ajaxvalidation, как это foreach