Dynamic Tabular Form


(Folumikeidowu) #1

I have these two models

Questions




    public function attributeLabels()

    {

        return [

            'id' => Yii::t('course', 'Question'),

            'question_category_id' => Yii::t('course', 'Question Category'),

            'question_course_id' => Yii::t('course', 'Course'),

            'instructor_id' => Yii::t('course', 'Instructor'),

            'question_name' => Yii::t('course', 'Question Name'),

            'question_text' => Yii::t('course', 'Question Text'),

            'default_mark' => Yii::t('course', 'Default Mark'),

            'penalty' => Yii::t('course', 'Penalty'),

            'qtype' => Yii::t('course', 'Question Type'),

            'mcq_answer_option' => Yii::t('course', 'Mcq Answer Option'),

            'is_status' => Yii::t('course', 'Is Status'),

        ];

    }


    public function getQuestionAnswers()

    {

        return $this->hasMany(\app\modules\course\models\QuestionAnswers::className(), ['question_id' => 'id']);

    } 



QuestionAnswers




    const UPDATE_TYPE_CREATE = 'create';

    const UPDATE_TYPE_UPDATE = 'update';

    const UPDATE_TYPE_DELETE = 'delete';


    const SCENARIO_BATCH_UPDATE = 'batchUpdate';




    private $_updateType;


    public function getUpdateType()

    {

        if (empty($this->_updateType)) {

            if ($this->isNewRecord) {

                $this->_updateType = self::UPDATE_TYPE_CREATE;

            } else {

                $this->_updateType = self::UPDATE_TYPE_UPDATE;

            }

        }


        return $this->_updateType;

    }


    public function setUpdateType($value)

    {

        $this->_updateType = $value;

    }


    public function rules()

    {

        return [

            ['updateType', 'required', 'on' => self::SCENARIO_BATCH_UPDATE],

            ['updateType',

                'in',

                'range' => [self::UPDATE_TYPE_CREATE, self::UPDATE_TYPE_UPDATE, self::UPDATE_TYPE_DELETE],

                'on' => self::SCENARIO_BATCH_UPDATE]

            ,            

            [['question_id'], 'integer'],

            //allowing it to be empty because it will be filled by the QuestionController

            ['question_id', 'required', 'except' => self::SCENARIO_BATCH_UPDATE],            

            [['answer'], 'required', 'message' => ''],

            [['answer', 'feedback'], 'string'],

            [['fraction'], 'number'],

            [['question_id', 'answer'], 'unique', 'targetAttribute' => ['question_id', 'answer'], 'message' => yii::t('course', 'Answer already exist for this Question.')],

        ];

    }


    public function attributeLabels()

    {

        return [

            'id' => 'Question Answer',

            'question_id' => 'Question',

            'answer' => 'Answer',

            'fraction' => 'Fraction',

            'feedback' => 'Feedback',

        ];

    }


    public function getQuestions()

    {

        return $this->hasOne(\app\modules\course\models\Questions::className(), ['id' => 'question_id']);

    } 



I am working on a Dynamic Tabular Form without using any Yii2 Extension. All necessary actions are performed in QuestionsController and questions(View)

QuestionsController




    public function actionCreate()

    {        

        $model = new Questions();

        $modelAnswers = [];              

        

        $formAnswers = Yii::$app->request->post('QuestionAnswers', []);

        foreach ($formAnswers as $i => $formAnswer) {

            $modelAnswer = new QuestionAnswers(['scenario' => QuestionAnswers::SCENARIO_BATCH_UPDATE]);

            $modelAnswer->setAttributes($formAnswer);

            $modelAnswers[] = $modelAnswer;

        }

        //handling if the addRow button has been pressed

        if (Yii::$app->request->post('addRow') == 'true') {

            $model->load(Yii::$app->request->post());

            $modelAnswers[] = new QuestionAnswers(['scenario' => QuestionAnswers::SCENARIO_BATCH_UPDATE]);

            return $this->render('create', [

                'model' => $model,

                'modelAnswers' => $modelAnswers

            ]);

        }

        if ($model->load(Yii::$app->request->post())) {   

            $model->course_id = $answerasc_id;

            $model->instructor_id = $instructorid;                      

            $model->created_by = Yii::$app->getid->getId();

            $model->created_at = new \yii\db\Expression('NOW()');                     

            

            if (Model::validateMultiple($modelAnswers) && $model->validate()) {

                $model->save();

                foreach($modelAnswers as $modelAnswer) 

                {

                    $modelAnswer->question_id = $model->id;

                    $modelAnswer->save();

                }

                return $this->redirect(['view', 'id' => $model->id]);

            }

        }

        return $this->render('create', [

            'model' => $model,

            'modelAnswers' => $modelAnswers

        ]);

    }



  1. When nothing is selected, we have

7663

tabular1.PNG

  1. I want to use qtype(Question Type) Dropdownlist to control what will be displayed and save in the models.

If qtype is equal to "True/False", then we have:

7664

tabular2.PNG

Also, if count is greater than 1, the Add Answer Button should be disabled. The attribute answer should be a dropdownlist

  1. I want to use qtype(Question Type) Dropdownlist to control what will be displayed and save in the models.

If qtype is equal to "Mutiple Choice Single Answer", then we have:

7665

tabular3.PNG

The attribute answer should be a textinput. The should be a field called "Correct Answer" in form of radiobutton, and only one should be selected.

  1. I want to use qtype(Question Type) Dropdownlist to control what will be displayed and save in the models.

If qtype is equal to "Mutiple Choice Multiple Answers", then we have:

The attribute answer should be a textinput. The should be a field called "Correct Answer" in form of checkbox, and multiple can be selected.

View




<?php $this->registerJs("

    $('.delete-button').click(function() {

        var detail = $(this).closest('.question-answers');

        var updateType = detail.find('.update-type');

        if (updateType.val() === " . json_encode(QuestionAnswers::UPDATE_TYPE_UPDATE) . ") {

            //marking the row for deletion

            updateType.val(" . json_encode(QuestionAnswers::UPDATE_TYPE_DELETE) . ");

            detail.hide();

        } else {

            //if the row is a new row, delete the row

            detail.remove();

        }


    });

");

?>

<div class="col-xs-12 col-lg-12">

<div class="questions-form">

<div class="box-success box view-item col-xs-12 col-lg-12">

    <?php $form = ActiveForm::begin([

                                        'enableClientValidation' => false


                                    ]); ?>    

<!-- GENERAL DETAILS -->

<div class="box box-info">   

  <div class="box-header with-border">

    <h3 class="box-title">General</h3>

      <div class="box-tools pull-right">

        <button type="button" class="btn btn-info" data-widget="collapse"><i class="fa fa-minus"></i></button> 

<!--        <button type="button" class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button>-->

      </div>

  </div>

  <!-- /.box-header -->

  <div class="box-body">

    <div class="table-responsive">  

    <div class="col-xs-12 col-lg-12 no-padding">  

        <div class="col-xs-12 col-sm-6 col-lg-6">    

            <?php $courseid = Yii::$app->getRequest()->getQueryParam('acs_id');?>

                <?= $form->field($model, 'question_category_id')->widget(Select2::classname(), [

                    'data' => ArrayHelper::map(QuestionCategories::find()->where(['course_id' => $courseid, 'is_status'=>0])->all(),'question_category_id','name'),

                    'language' => 'en',

                    'options' => ['placeholder' => 'Select Question Category ...'],

                    'pluginOptions' => [

                    'allowClear' => true

                    ],

                ]);

                ?> 

        </div>

        <div class="col-xs-12 col-sm-6 col-lg-6">    

            <?= $form->field($model, 'question_name')->textInput(['maxlength' => 100]) ?>

        </div>        

    </div>    

    <div class="col-xs-12 col-lg-12 no-padding"> 

        <div class="col-xs-12 col-sm-12 col-lg-12">

                <?= $form->field($model, 'question_text')->textInput(['maxlength' => 100]) ?>      

        </div>

    </div> 

    <div class="col-xs-12 col-lg-12 no-padding">  

        <div class="col-xs-12 col-sm-6 col-lg-6"> 

            <?= $form->field($model, 'default_mark')->textInput(['maxlength' => 12, 'value' => '1']) ?>

        </div>

        <div class="col-xs-12 col-sm-6 col-lg-6">    

                <?= $form->field($model, 'qtype')->widget(Select2::classname(), [

                    'data' => $model->getQuestionType(),

                    'language' => 'en',

                    'options' => ['placeholder' => 'Select Question Type ...'],

                    'pluginOptions' => [

                    'allowClear' => true

                    ],

                ]);

                ?>               

        </div>        

    </div>         

    </div>

  </div>  

</div>    

<!-- FORMAT -->

<div class="box box-success">   

  <div class="box-header with-border">

    <h3 class="box-title"><i class="glyphicon glyphicon-user"></i> Question Answers</h3>

      <div class="box-tools pull-right">    

        <button type="button" class="btn btn-success" data-widget="collapse"><i class="fa fa-minus"></i></button> 

        <!--<button type="button" class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button>-->

      </div>

  </div>   

<!--   /.box-header -->

  <div class="box-body">

    <div class="table-responsive">     

    <div class="padding-v-md">

        <div class="line line-dashed"></div>

    </div>  

        

    <div class="panel panel-default">

        <div class="panel-heading">

            <i class="fa fa-envelope"></i> Question Answers

            <button type="button" class="pull-right add-item btn btn-success btn-xs"></button>

            <div class="clearfix"></div>

        </div>  

        

        <div class="panel-body container-items truefalse-data"><!-- widgetContainer -->        

            <?php foreach ($modelAnswers as $i => $modelAnswer) : ?>

<!--                <div class="item panel panel-default"> widgetBody -->

            <div class="row question-answers question-answers-<?= $i ?>">

                    <div class="panel-heading">

                        <span class="panel-title-address">Question Answers: <?= ($i + 1) ?></span>

                        

                        <div class="clearfix"></div>

                    </div>

                    <div class="panel-body">

                        <?= Html::activeHiddenInput($modelAnswer, "[$i]id") ?>

                        <?= Html::activeHiddenInput($modelAnswer, "[$i]updateType", ['class' => 'update-type']) ?>


                        <div class="row">

                            <div class="col-sm-11">

                                <?= $form->field($modelAnswer, "[{$i}]answer")->widget(Select2::classname(), [

                                 'data' => $modelAnswer->getTrueFalse(),

                                 'language' => 'en',

                                 'options' => ['placeholder' => 'Select Question Type ...'],

                                 'pluginOptions' => [

                                 'allowClear' => true

                                 ],

                             ]);

                             ?>                                

                        </div>                                

                            <div class="col-md-1">

                                <?= Html::button('x', ['class' => 'delete-button btn btn-danger', 'data-target' => "question-answers-$i"]) ?>

                            </div>  

                            <div class="col-sm-12">

                                <?= $form->field($modelAnswer, "[$i]feedback")->textInput(['maxlength' => 100]) ?>                                 

                            </div>                            

                        </div><!-- end:row -->

                    </div>

                </div>

            <?php endforeach; ?>

        </div>

        

        <div class="panel-body container-items mcsa-data"><!-- widgetContainer -->        

            <?php foreach ($modelAnswers as $i => $modelAnswer) : ?>

<!--                <div class="item panel panel-default"> widgetBody -->

            <div class="row question-answers question-answers-<?= $i ?>">

                    <div class="panel-heading">

                        <span class="panel-title-address">Question Answers: <?= ($i + 1) ?></span>

                        

                        <div class="clearfix"></div>

                    </div>

                    <div class="panel-body">

                        <?= Html::activeHiddenInput($modelAnswer, "[$i]id") ?>

                        <?= Html::activeHiddenInput($modelAnswer, "[$i]updateType", ['class' => 'update-type']) ?>


                        <div class="row">

                            <div class="col-sm-11">

                                <?= $form->field($modelAnswer, "[$i]answer")->textInput(['maxlength' => 100]) ?>

                        </div>                                

                            <div class="col-md-1">

                                <?= Html::button('x', ['class' => 'delete-button btn btn-danger', 'data-target' => "question-answers-$i"]) ?>

                            </div>  

                            <div class="col-sm-12">

                                 <?= $form->field($modelAnswer, "[$i]feedback")->textInput(['maxlength' => 100]) ?>

                            </div>                            

                        </div><!-- end:row -->

                    </div>

                </div>

            <?php endforeach; ?>

        </div>

        

        <div class="panel-body container-items mcma-data"><!-- widgetContainer -->        

            <?php foreach ($modelAnswers as $i => $modelAnswer) : ?>

<!--                <div class="item panel panel-default"> widgetBody -->

            <div class="row question-answers question-answers-<?= $i ?>">

                    <div class="panel-heading">

                        <span class="panel-title-address">Question Answers: <?= ($i + 1) ?></span>

                        

                        <div class="clearfix"></div>

                    </div>

                    <div class="panel-body">

                        <?= Html::activeHiddenInput($modelAnswer, "[$i]id") ?>

                        <?= Html::activeHiddenInput($modelAnswer, "[$i]updateType", ['class' => 'update-type']) ?>


                        <div class="row">

                            <div class="col-sm-11">

                                <?= $form->field($modelAnswer, "[$i]answer")->textInput(['maxlength' => 100]) ?>

                        </div>                                

                            <div class="col-md-1">

                                <?= Html::button('x', ['class' => 'delete-button btn btn-danger', 'data-target' => "question-answers-$i"]) ?>

                            </div>  

                            <div class="col-sm-12">

                                 <?= $form->field($modelAnswer, "[$i]feedback")->textInput(['maxlength' => 100]) ?>

                            </div>                            

                        </div><!-- end:row -->

                    </div>

                </div>

            <?php endforeach; ?>

        </div>        


    </div>

    

    </div>

  </div>  

</div>

<!--</div>-->  


    <div class="form-group">

        <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>

         <?= Html::submitButton('Add Answer', ['name' => 'addRow', 'value' => 'true', 'class' => 'btn btn-info']) ?>

    </div>


    <?php ActiveForm::end(); ?>


</div>

</div>

</div>


<script>

$(document).ready(function(){

	var chkvalue = $('#questions-qtype').val();

	if(chkvalue=='True/False') {

		$(".mcsa-data").hide();

                $(".mcma-data").hide();

		$(".truefalse-data").show();

	}

	else if(chkvalue=='Multiple Choice Single Answer') {

		//$("#cheque-data").css("display","block");

		$(".mcsa-data").show();

                $(".mcma-data").hide();

		$(".truefalse-data").hide();

	}

        

	else if(chkvalue=='Multiple Choice Multiple Answers') {

		//$("#cheque-data").css("display","block");

		$(".mcsa-data").hide();

                $(".mcma-data").show();

		$(".truefalse-data").hide();

	}        

	else {

		//$("#cheque-data").css("display","block");

		$(".mcsa-data").hide();

                $(".mcma-data").hide();

		$(".truefalse-data").hide();

	}        

	$("#questions-qtype").change(function(){

	var chkvalue = $('#questions-qtype').val();

	if(chkvalue=='True/False') {

		$(".mcsa-data").hide();

                $(".mcma-data").hide();

		$(".truefalse-data").show();

	}

	else if(chkvalue=='Multiple Choice Single Answer') {

		//$("#cheque-data").css("display","block");

		$(".mcsa-data").show();

                $(".mcma-data").hide();

		$(".truefalse-data").hide();

	}

        

	else if(chkvalue=='Multiple Choice Multiple Answers') {

		//$("#cheque-data").css("display","block");

		$(".mcsa-data").hide();

                $(".mcma-data").show();

		$(".truefalse-data").hide();

	}        

	else {

		//$("#cheque-data").css("display","block");

		$(".mcsa-data").hide();

                $(".mcma-data").hide();

		$(".truefalse-data").hide();

	}  

	});

});

</script>