-1

I am new to Yii2 and have been trying to work out how to hide/show certain fields on the form based on a dropDownList selection with client-side validation.

Basically I have a model and form view that collects information relating to 'candidates' and I wish to apply the following logic:

  1. Only display the fields 'assigned_to' and 'phone' if the dropDownList selection for 'qualification_id' = 2.

  2. The fields 'assigned_to' and 'phone' are required if 'qualification_id' = 2 (else optional)

My code is as follows, albeit not working as I need it to. The client-side validation is not working (i.e.'assigned_to' and 'phone' are not required when qualification_id = 2). I have not been able to work out how to hide/show the fields dynamically based on the 'qualification_id' selection. I assume some javascript is required for this.

Any assistance would be greatly appreciated!

MODEL:


namespace frontend\models;

use Yii;

/**
 * This is the model class for table "candidate".
 *
 * @property int $candidate_id
 * @property string $name
 * @property int $qualification_id
 * @property string $assigned_to
 * @property string $phone

    public static function tableName()
    {
        return 'candidate';
    }


    public function rules()
    {
        return [
            [['candidate_id', 'qualification_id', 'name'], 'required']
            [['candidate_id', 'qualification_id'], 'integer'],
            [['name', 'assigned_to’, 'phone’], 'string'],

            [['assigned_to', 'phone'],'required','when'=>function($model){
            
                return ($model->qualification_id == 2);
                },
                                    
            'whenClient'=>"function(attribute, value){
                    return $('#qualification_id').val() == 2; 
                                    
                 }"],

VIEW (form):


<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use frontend\models\QualificationType;

/* @var $this yii\web\View */
/* @var $model frontend\models\Candidate */
/* @var $form yii\widgets\ActiveForm */

?>


<div class="candidate-form">

    <?php $form = ActiveForm::begin(); ?>


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


    <?= $form->field($model, 'qualification_id')->dropDownList(
        ArrayHelper::map(QualificationType::find()->all(),'qualification_id','qualification'),
        [
        'prompt'=>'Select...',
        'id' => 'review_type_id', 
        'onchange' => 'changeQualification()'
]
    ) ?>

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

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

    <div class="form-group">
        <?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
    
    </div>

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

</div>

<?php

    $script = <<<JS
    function changeQualification() {
      if ($('#qualification_id').val() == 2) {
       $('#assigned_to').show();
       $('#name).show();

      } else {

       $('#assigned_to).hide();
       $('#name).hide();
      }
    }
    JS;

    $this->registerJs($script);

    ?>

Adsar
  • 1
  • 3
  • First of all there's a typo, i hope thats just here and not in your actual code: `... $form->field($model, 'assigned_to)-> ...` (where is the closing apostrophe (= `'`) after asigned_to?). Secondly: have you tried a simple javascript/jquery script which would hide the input? [How can I show and hide elements based on selected option with jQuery?](https://stackoverflow.com/questions/2975521/how-can-i-show-and-hide-elements-based-on-selected-option-with-jquery) – Definitely not Rafal Jun 29 '21 at 10:27
  • Thanks, fortunately the closing apostrophe is in my code. I tried the Javascript in SmartMan21Sen response below but haven't been able to get that to work. – Adsar Jun 29 '21 at 11:08
  • What didnt work? What did you try? Update your question with the current code. How are else supposed to help you? Your problem has not much to do with Yii2 itself. Its just that you use that framework. Your question is *"How do i hide an HTML element via JavaScript when i select the value '2' in my dropdown"*. From what i can see you seem to be struggeling with that fact that you dont know the id of the input that you generate with `$form->field($model, 'assigned_to)->textInput(['maxlength' => true])` (the apostrophe typo still exists till this day). Use your HTML inspector in your browser. – Definitely not Rafal Jun 30 '21 at 07:15
  • Hi Definitely not Rafal, thanks for persisting with me. You are correct in that I am stuck on the javascript aspect. I have updated the question with the current code I am using. The issue I am still facing is that the javascript function doesn't seem to be recognised. I wondered if I have added it incorrectly to the view or if I need to enable js in yii2 or something. Any help wouldbe greatly appreciated. Thanks, Adsar – Adsar Jul 01 '21 at 08:02
  • Before going any further: do you understand what each added line means? Because I dont think you do. As an example: the `$('#assigned_to')` command, searches in current document for an HTML element with `id="assigned_to"`. Im 99.99999% sure that `$form->field($model, 'assigned_to')->textInput(['maxlength' => true])` does not generate an HTML element with that id, hence why nothing happens. You need to look at the generated HTML and check what ID is being generated, thats what you need to use instead of just assuming the generated ID is `assigned_to`. – Definitely not Rafal Jul 01 '21 at 10:29
  • Thanks for providing this explanation. You are right, I inspected the page and found that the HTML element generated is id="tenancy-assigned_to". I have changed the ids in my code to what I have found in the HTML document but the other issue remains. changeQualification is not defined at HTMLSelectElement.onchange. This is where I was thinking the js function changeQualification() has not been added correctly. It doesn't seem to be recognised. Thanks again. – Adsar Jul 01 '21 at 12:16
  • Its most likely not registered because of the scope. Take a look once again in the html inspector and find your definition in it. Youre more helped with a basic course of how HTML, PHP, JavaScript works. We are not going to hold you by your hand while you happily code every single step. This is not how this site is intended. You need to understand how HTML, PHP. JavaScript works if you want to use these. Using a Framework which uses those, does not make easier for you. – Definitely not Rafal Jul 01 '21 at 14:12

1 Answers1

0

Please try like this

In view

<div class="candidate-form">
        <?php $form = ActiveForm::begin(); ?>
        <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
        <?= $form->field($model, 'qualification_id')->dropDownList(
            ArrayHelper::map(QualificationType::find()->all(),'qualification_id','qualification'),
            ['prompt'=>'Select...', 'id' => 'qualification_id', 'onchange' => 'changeQualificationType()']
        ) ?>
    
        <?= $form->field($model, 'assigned_to)->textInput(['id' => 'assigned_to_Input', 'maxlength' => true]) ?>
    
        <?= $form->field($model, 'phone')->textInput(['id' => 'phone_input', 'maxlength' => true]) ?>
    
        <div class="form-group">
            <?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
        
        </div>
    
        <?php ActiveForm::end(); ?>
    
    </div>



<?php
$script = <<<JS
    function changeQualificationType() {
      if ($('#qualification_id').val() == 2) {
       $('#assigned_to_input').closest('.form-group').show();
       $('#phone_input').closest('.form-group').show();
      } else {
       $('#assigned_to_input').closest('.form-group').hide();
       $('#phone_input').closest('.form-group').hide();
      }
    }
JS;
$this->registerJs($script);

In Model

public function rules()
    {
        return [
            [['candidate_id', 'qualification_id', 'name'], 'required']
            [['candidate_id', 'qualification_id'], 'integer'],
            [['name', 'assignedTo, 'phone’], 'string'],

            [['assignedTo', 'phone'],'required','when'=>function($model){
            
                return ($model->qualification_id == 2);
                },
                                    
            'whenClient'=>"function(attribute, value){
                    return $('#qualification_id').val() == 2; 
                                    
                 }"],

Don't forget to set custom id in ActiveFormField. All of field id should be matched with functions of Jquery and Model.

  • Hi SmartMan21Sen, – Adsar Jun 29 '21 at 10:57
  • Hi SmartMan21Sen, Thanks so much for your assistance. Unfortunately it is still not behaving as expected. The fields that I want to hide are displayed prior to the dropDownList selection and nothing seems to happen when a selection is made whether it be == 2 or another option. I only want to display these fields if the qualification_id selection == 2. Am I missing something? – Adsar Jun 29 '21 at 11:03
  • HI Adsar. can I help you in remote ? – SmartMan21Cen Jun 29 '21 at 11:14
  • Please check if attached javascript code is working correctly – SmartMan21Cen Jun 29 '21 at 11:24
  • SmartMan21Sen, the Javascript doesn't seem to be working. It is not hiding and showing the fields as per the condition. – Adsar Jun 29 '21 at 12:12
  • Do I need to have _input after the field names in the javascript code (e.g. '#assigned_to_input' or 'assigned_to' to match the field names in the model and form)? – Adsar Jun 29 '21 at 12:22
  • No. You should use same tag id in view, not in model – SmartMan21Cen Jun 29 '21 at 13:37
  • You don't have to change model's field name. Just should use same tag id in view and js function – SmartMan21Cen Jun 29 '21 at 13:38
  • Thanks again SmartMan21Sen, It looks like the javascript function changeQualificationType is not defined. Perhaps this has been added in the wrong place? Should this be inside the ActiveForm perhaps? I have played around with that but it doesn't seem to make a difference. – Adsar Jun 29 '21 at 23:28
  • The error displayed in the console is Uncaught ReferenceError: changeQualificationType is not defined at HTMLSelectElement.onchange. Hopefully this points us towards a solution. Your assistance is very much appreciated. – Adsar Jun 29 '21 at 23:34
  • Yes. This javascript function should work. Please add changeQualificationType function in proper position. If it is working, issue will be solved – SmartMan21Cen Jun 30 '21 at 02:12
  • I have added it to the location at the bottom of the view, beneath the ActiveForm div (as per your initial response). Is this the proper position? registerJs($script); ?> – Adsar Jun 30 '21 at 06:34
  • Right. Please inspect page and check if javascript function was added – SmartMan21Cen Jun 30 '21 at 10:15
  • This is in the page. Looks like it is added. registerJs($script); ?> – Adsar Jun 30 '21 at 10:36
  • Ah, I think your yii project does not support JS expression. Are there any js file that you use for this page? then please add this function in js file – SmartMan21Cen Jun 30 '21 at 10:56
  • Ah yes. Tat would make sense, although I have not created any other js files to be used by this page. Do I need to enable js expression? – Adsar Jun 30 '21 at 12:14
  • Yes, js function should be ran. – SmartMan21Cen Jun 30 '21 at 14:10