CActiveForm submitted with ajax

Hi,

I am submitting a CActiveForm with an ajaxSubmitButton.I have set enableClientValidation to true-(doesnt matter ,the problem is the same with both enableAjaxValidation and enableClientValidation set to true).So,clientvalidation works as expected.For example leaving a required field empty,validation turns the input into red,and the error message appears.Now when I click the submit button,the ajax POST submission is made,even if the form did not validate.Why?Here is my form:





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

	'id'=>'comment-form',

   // 'enableAjaxValidation'=>true,

   'enableClientValidation'=>true,

    'focus'=>array($model,'author'),

    'clientOptions'=>array('validateOnSubmit'=>true, 

                                      'validateOnType'=>false,


                                                                         	),

)); ?>

<?php echo $form->errorSummary($model); ?>

	<p class="note">Fields with <span class="required">*</span> are required.</p>


	<div class="row">

		<?php echo $form->labelEx($model,'author'); ?>

		<?php echo $form->textField($model,'author',array('size'=>60,'maxlength'=>128)); ?>

		<?php echo $form->error($model,'author'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'email'); ?>

		<?php echo $form->textField($model,'email',array('size'=>60,'maxlength'=>128)); ?>

		<?php echo $form->error($model,'email'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'url'); ?>

		<?php echo $form->textField($model,'url',array('size'=>60,'maxlength'=>128)); ?>

		<?php echo $form->error($model,'url'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'content'); ?>

		<?php echo $form->textArea($model,'content',array('rows'=>6, 'cols'=>50)); ?>

		<?php echo $form->error($model,'content'); ?>

	</div>


        <div class="row">


		<?php echo $form->hiddenField($model,'article_id',array('value'=>$article_id)); ?>


	</div>


	<div class="row buttons">

		<?php 

              //  FB::setEnabled('false');

            //  echo  CHtml::submitButton($model->isNewRecord ? 'Submit' : 'Save');


                echo  CHtml::ajaxSubmitButton( $model->isNewRecord ? 'Submit' : 'Save',

                                                               	$this->createUrl('article/saveComment'),

                                                               	array('type'=>'POST',

                                                                     	'success'=>'function(data) {

                                                                                            var response= jQuery.parseJSON (data);


                                                                                            if (response.success ==true){

                                                                                     	$("#ajaxstatus").append(response.message)

                                                                                                             	.addClass("flash-success")

                                                                                                             	.fadeToggle(2000, "linear");

                                                                                                              $("#comment-form").slideToggle(1500);

                                                                                                    }

                                                                                            else{

                                                                                         	$("#ajaxstatus").hide().

                                                                                                                  addClass("flash-error")

                                                                                                             	.append(response.message).fadeIn(2000);

                                                                                                             	$("#comment-form").each (function(){

                                                                                                                              this.reset();

                                                                                                                       	});

                                                                                                }


                                                                                            }' //success

                                                                      

                                                                             	),

                                                                   	array('type'=>'submit')

                                                                                                      );


                ?>

	</div>


<?php $this->endWidget(); ?>






I can see in my firebug console that the ajax POST call to action article/saveComment is made,even if validation fails(required fields are empty).Why?

Thanks in advance,I will appreciate your help.

I thought the idea of the ClientValidation was to be used as a “suggestion” for the user to show which attributes will fail when submitting the form. The benefit is that you won’t have to use ajaxValidation which could lead to bad performance when used a lot. The “real validation” will always be on the server side to be more secure (just think about a user that disables javascript). I understand your problem but I think that this is the normal behavior and you would have to add additional javascript if you want to stop submission (e.g.: adding a javascript variable that is changed to false if the js validation fails and which is checked before every submit)

just remove


   // 'enableAjaxValidation'=>true,

   'enableClientValidation'=>true,

    'focus'=>array($model,'author'),

    'clientOptions'=>array('validateOnSubmit'=>true, 'validateOnType'=>false,),




its because you have two ajax calls, you have to validate your form after click let the php do that for you and return data in ajax as you did

Igor and Haensel thank you both,yes the "real "validation happens on the server,but I am somehow obsessed with the idea that the ajax submission should not be made at all as unnecessary if the client side says that it will fail.Blame this on my Adobe Flex background,this is how things are done in Flex.Well I have found a very interesting snippet in another forum post.I think it makes possible -with ‘enableClientValidation’ set to true- to post a form with ajax only if validation succeeds on the client side.The final ajax submission is the only server traffic that will ever take place,look at this:




$ajaxUrl=CController::createUrl('report/ajaxCreate');

$formId='report-form';$js=<<<EODjs:function(form, data, hasError) {    if (!hasError) {  


      jQuery.ajax({'type':'POST','url':'$ajaxUrl','cache':false,'data':$("#$formId").serialize(),'success':function(html){jQuery("#reportform").html(html)}}); 

   	return false;    }}EOD;


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

                       	'id'=>$formId,        'enableAjaxValidation'=>true,   

                          'clientOptions'=>array('validateOnSubmit'=>true,  

                       	'afterValidate'=>$js))); ?>  

   	<p class="note">Fields with <span class="required">*</span> are required.</p>   

   		<?php echo $form->errorSummary($model); ?>   

      <div class="row">        

 	<?php echo $form->labelEx($model,'email'); ?> 

   	<?php echo $form->textField($model,'email'); ?>   	

     	<?php echo $form->error($model,'email'); ?>  

        </div>    

   <div class="row">

   <?php echo $form->labelEx($model,'content'); ?>

   <?php echo $form->textField($model,'content',array('size'=>60,'maxlength'=>16384)); ?>  

    <?php echo $form->error($model,'content'); ?> 

 	</div>

    <div class="row buttons">        

<?php echo CHtml::submitButton('Submit'); ?> 

   </div><?php $this->endWidget(); ?>

hasError is the javascript variable that Haensel talks about,all this is made possible with the recent addition of afterValidate as one of the clientOptions in CActiveForm.The snippet uses ‘enableAjaxValidation’=>true, but I am tempted to believe it should work with enableclientvalidation

too.And surprisingly,the submit button is a regular submit button ,not an ajaxsubmitbutton.After one clicks submit, clientvalidation and/or ajaxvalidation is performed,and if it fails the submission is never made.As I said,if this works with clientvalidation,no ajax request is ever made apart from the actual submission that is guaranteed to validate on the server as well.Can’t wait to try this.Here is the link to the original post:

Forum Post

UPDATE:I am cheerful here,This snippets works!I tested with clientvalidation set to true.The form is submitted with ajax,ONLY if it validates on client side,no POST request is ever made to the server apart from the actual submission.Ofcourse it also works with javascript turned off,a regular POST request to the server happens on this occasion.

Thumbs up for Yii,because there is a ton of core Yii javascript required to make this happen.

Powerful stuff!

There should be a little wiki tutorial for this,I think it’s very useful info.

thank ‘yii forum’, i found out this post ;)

PS - is there any jquery function to reset CActiveForm input fields and messagens to default after ajax submission ?

something like




$.fn.yiilistview.update(CLISTVIEW_ID)



for CListView, that will update it’s data but for CActiveForm that would set its fields to default state ?

thanks in advance

Thank you drumaddict for this solution.

The best I have found!

optikool,

you can reset your form with:




$("#$formId")[0].reset();