Ajax for hiding fields on a ajax-validation enabled form

Currently I am trying to be able to hide / show various fields based on values of other fields. Originally I used JavaScript to literally hide / show them, however my team leader wants us to use a server call instead (I dunno why, but alas I am bound to this restriction).

Currently, the setup I am using to do this uses a CActiveForm widget with ajax validation enabled. The data entered in the form is singleton and thus is only ‘added’ the first time the user uses this form and is only updated there after.

Whenever there is a field or fields that will be hidden based on a value they are wrapped in a container <div> tag and use a <?php if(condition): ?> / <?php endif; ?> to encapsulate said fields. The field who’s value determines the visibility if then given a ajax link that makes a call to the controller.

So for example say I have a RadioButtonList with options Yes / No and when the user selects ‘Yes’ a textfield is displayed, and when a user selects ‘No’ the testfield is hidden.

The code in the view would look like this:




<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'my-form',

	'enableAjaxValidation'=>true,


)); ?>




<div class="row">

 <?php echo $form->labelEx($myModel,'rbValue'); ?>

 <?php echo $form->radioButtonList($myModel,'rbValue',

                                   array('t'=>'Yes',

                                         'f'=>'No'),

                                          array('onchange'=>CHtml::ajax(array('type'=>'POST',

                                                'url'=>CController::createUrl('AjaxToggleFunction'),

                                                'update'=>'#toggleDiv',

                                                'data'=>'js:jQuery(this).serialize()' ,)))); ?>

 <?php echo $form->error($myModel,'rbValue'); ?>

</div>





<div id="toggleDiv">	


 <?php if($myModel->rbValue == 't'): ?>

   <div class="row">

    <?php echo $form->labelEx($myModel,'textFieldAttrib'); ?>

    <?php echo $form->textField($myModel,'textFieldAttrib'); ?>

    <?php echo $form->error($myModel,'textFieldAttrib'); ?>

   </div>


 <?php endif; ?>


</div>




For the controller I have code looking something like this:


public function actionAjaxToggleFunction()

{

 //if user selected 'Yes'

 if(isset($_POST['MyModel']) && $_POST['MyModel'][rbValue] == 't')

 {

  //load an empty model of the needed type

  $myModel = new MyModel;

  

  echo '<div class="row">';

  echo CHtml::activeLabelEx($committee, 'filing_state');

  echo CHtml::activedropDownList($committee, 'filing_state',$this->getStateValues(true));

  //echo CHtml::error($committee, 'filing_state'); //always shows no error since no validation has been done

  echo '</div>';

  

 }


 

}

This works in the sense that the correct fields are written or hidden within the div tag and are updated correctly upon form submission. The problem is that the newly created fields do not trigger any sort of Ajax validation. If the field is created by the $form variable then Ajax-validation does indeed work as expected, but if the field is created by the Ajax response it no longer triggers a post to the server when the data is changed. If another field that already exists changes and makes an Ajax-validation post then the new field is validated but otherwise nothing. I’m clearly missing something, and also fear I may need to write custom code to validate any hideable fields. The project I’m working on will have dozens of these hideable fields.

If anyone has any advise I’d sure appreciate it.

As you already noticed… only fields created by the $form variable do trigger an ajax validation…

CActiveForm is a widget… in the view… when you create the widget you assign it to the $form variable…

by using $form->error()… this widget "remembers" the attribute name and later sets an appropriate jQuery event for that input field…

One idea that comes to mind would be to put all this "special" fields in the view…

the fields/rows that should not be visible you can hide with a CSS class (display:hidden)… so they would not be visible… but an jQuery validation event will be set for them…

then on AJAX you can just change the class of that field/row…

NOTE: you can edit the title by using the full editor