Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding some more fields to the form in yii2 using ajax

Tags:

ajax

php

yii2

I have a Yii2 form:

<?php $form = ActiveForm::begin(['id' => 'que']); ?>
    <?php echo $form->field($model, 'type')
            ->dropDownList($questionTypes, [
                'class' => 'form-control ng-pristine ng-valid ng-touched',
                'prompt' => 'Select question type',
                'ng-model' => 'que.type',
                'ng-change' => 'addAnswerOptions(que);',
        ]);
    ?>
<?php ActiveForm::end(); ?>

On the basis of selected dropdown value, I have to add some more fields to the same form of the same model. What fields will be added, is totally depend on the dropdown value.

How can I do this?

like image 836
Kuldeep Dangi Avatar asked Apr 12 '15 06:04

Kuldeep Dangi


1 Answers

From the information you give out here is what I would suggest.

1) Dynamic - no AJAX

Build your form with all the fields you need, just contain each "scenario" in a separate div like follows:

<?php $form = ActiveForm::begin(['id' => 'que']); ?>
    <?php echo $form->field($model, 'type')
            ->dropDownList($questionTypes, [
                'class' => 'form-control ng-pristine ng-valid ng-touched',
                'prompt' => 'Select question type',
                'ng-model' => 'que.type',
                'ng-change' => 'addAnswerOptions(que);',
        ]);
    ?>
    <div class="form-option" data-type="class" style="display:none;">
        <?php
            // ... fields here for case type == class
        ?>
    </div>
    <div class="form-option" data-type="prompt" style="display:none;">
        <?php
            // ... fields here for case type == prompt
        ?>
    </div>
    <div class="form-option" data-type="ng-model" style="display:none;">
        <?php
            // ... fields here for case type == ng-model
        ?>
    </div>
    <div class="form-option" data-type="ng-change" style="display:none;">
        <?php
            // ... fields here for case type == ng-change
        ?>
    </div>
<?php ActiveForm::end(); ?>

Then you will want to register Javascript code to display the correct blocs depending on which dropdown option was selected. Bellow is an example using JQuery:

$(document).ready(function(){
    $('select.form-control').change(function(){
        $('.form-option').hide(); // hide all options if an option is showing
        var index = $('select.form-control').index();
        $('div[data-type="'+index+'"]').show(); //show the correct fields
    });
});

If you're going to go this way I suggest you use AJAX validation for your form. It will avoid you having to deal with a headache on page reload.

Once your form is submitted you will have to handle each case in your controller. You can either use a simple set of if() statements that check the drop down value. Or you can set your model validation scenario according to the drop down value.

The advantage of this is that it will be quicker and you will be able to take advantage of ActiveForm. the cons are that you need to know which fields you want to display for each option, and it doesn't allow you to cumulate n number of fields when you don't know how much n is.

2) Using Ajax

In the event that you want to use ajax calls to load the extra form fields you will have to make a controller/action combination that will return the fields depending on the type that you pass in the GET

This action will generate the html of the fields you want to display. Here's an example:

public function actionAjaxFields($type)
{
    $html = '';
    if($type == "class")
    {
        $html .= Html::textInput('Field1');
    }
    elseif($type == "prompt")
    {
        $html .= Html::textInput('Field2');
    }
    else
    {
        // etc...
    }
    return $html;
}

Note that you can also pass a user id to this method which will allow you to generate a model and use Html::activeTextInput(), however you will not be able to take advantage of ActiveForm features.

Once this is done, you should bind a function to the change event of the dropdown and use something along the lines of :

var responsePromise = $http.get("controller/ajax-fields", {params: {type: <type-from-dropdown>}});

Unfortunately I do not know much about angularjs so this is the extent of the help I can give on the javascript side of things. I'm sure there's more than enough information on google/stackoverflow about binding events and appending data to the DOM in angularjs to get you running.

Let me know if I can be of any extra help on the Yii2 side.

like image 105
Pomme.Verte Avatar answered Nov 17 '22 01:11

Pomme.Verte