Disable ajax validation temporarily?

Hi.

I’ve followed the cookbook example for creating a dropdown list of states.

The state dropdown list gets dynamically modified whenever the user chooses

a different country from the country dropdown list. It works fine and dandy.

I’m using activeDropDownList and activeTextField to create form fields on the page,

and I’ve enabled ajax validation with:


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

	'id'=>'customer-form',

	'enableAjaxValidation'=>true,

)); 

So far, so good.

The problem is, while the ajax validation is fabulous for validating the user’s

first and last name, email address, etc., I find it klunky to have it validate

the entire form when the user modifies the value of the country select list.

The effect, when all form fields are correct, is for them to turn green.

It’s a usability issue, not a functional issue. But I’d really LOVE to have

my cake and eat it too, i.e.

  • Ajax-validate the form when it’s submitted, or when the user, for instance

    places their mouse in the "first_name" text box, and then leaves the text box,

    without entering any values.

  • NOT ajax-validate the form when the user merely selects a different

    value from the "country_id" dropdown list.

Possible?

Thanks!

Emily

Did you look at the validate options of ajaxvalidation method in the specific controller:


protected function performAjaxValidation($model)

	{

		if(isset($_POST['ajax']) && $_POST['ajax']==='post-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

	}

I think you might be able to manage this in echo CActiveForm::validate($model);

Look here http://www.yiiframework.com/doc/api/CActiveForm#validate-detail for more details on how to exclude attributes from the above validation. Looks like you can pass through a second parameter with the attributes that you would like to validate which gives you the option to specify all but the one you wish to exclude.

Hope this helps

Thanks so much for the great idea. I did indeed look at performAjaxValidation() to see if I could customize it.

I’m trying to do something slightly different, however, than what you suggest.

You’re suggesting that I change which fields get validated. If that were my goal, that would

indeed be simple to do by modifying performAjaxValidation().

However, what I actually want to modify is whether or not the validation happens at all.

I.e., if the action being performed is

dynamicStates

then I don’t want the validation to run;

otherwise, I do.

So, in order to modify performAjaxValidation(), I need to know WHO is calling performAjaxValidation().

I looked at the $_REQUEST, and there’s nothing in it that tells me that

dynamicStates

is being called rather than a regular form submission.

In my _form.php view, I even tried passing along extra parameters when creating the URL for the Ajax call.




// Create a "validate" parameter to include on the URL when making the Ajax request

[b]$urlParams = array('validate'=>'false');[/b]


// Create the dropdown

echo CHtml::activeDropDownList($model,

	 'country_id', 

	$model->getCountryOptions(),

	array(

	'ajax' => array(

		'type'=>'POST', //request type

		 'url'=>CController::createUrl('customer/dynamicStates',[b] $urlParams),[/b]

                 'dataType' => 'json',

                 'success' => 'function(data) {

 		    $("#div_state").html(data["div_state"]);

		   $("#div_province").attr("style", data["div_province_style"]);

		 }',

		 )))



Even adding that, I did not end up with the variable "validate" in the $_REQUEST, when I examined the

$_REQUEST in the performAjaxValidation() method.

So the bottom line is: how can performAjaxValidation() tell who’s calling it, so that it can

decide NOT to validate under certain conditions?

Thanks again, great forum!

Emily

If I understood you…

when actionDynamicState calls performAjaxValidation you don’t want the validation to happen

for every other action validation should happen

If that is what you need, just add a parameter to performAjaxValidator like:




   protected function performAjaxValidation($model,$validate=true)

	{

		if($validate && isset($_POST['ajax']) && $_POST['ajax']==='...-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

	}



and call it from actionDynamicState with performAjaxvalidation($model,false)

Did you try to remove the following line from your action method:


$this->performAjaxValidation($model);

I think this should prevent the ajax validation from executing. Another thought is set the ‘enableAjaxValidation’=>false, in your view file that is rendered by your actionDynamicState.

Hope this helps.

Mdomba,

Mdomba > If I understood you, when actionDynamicState calls performAjaxValidation you

Mdomba > don’t want the validation to happen for every other action validation should happen.

Correct! That’s exactly what I need.

Here’s the problem:

CustomerController::actionDynamicStates()

is not making an explicit call to the performAjaxValidation() function!

The action which is making that call to performAjaxValidation() is the

CustomerController::actionUpdate() (!)

I know this because I put in some "print to a log file" statements in both action functions.

So now this begs the question: why is actionUpdate() being called when only actionDynamicStates() should be called.

This script is, of course, at the following URL:

index.php/hqadmin/update/id/203

If I click the submit button on that page, I expect actionUpdate() to be called, but I do not expect it to be called when I select a different country from the country dropdown.

If I were to submit the form on that page, I expect actionUpdate() to get called.

But it’s getting called when I select a different country from the country dropdown!

I know we’re on the right track, if I can just figure out why actionUpdate() is being called IN ADDITION to actionDynamicStates(), every time the user selects a different country from the dropdown.

I did a "view source" in my browser to look at the generated Ajax call. I include it below (with newlines added for readability.) This may come down to a jquery issue? Is there some call to say, "do NOT submit the form?"




<script type="text/javascript">

/*<![CDATA[*/

jQuery(function($) {

   jQuery('body').delegate(

      '#Customer_country_id',

      'change',

      function(){jQuery.ajax({'type':'POST',

                              'url':'/index.php/customer/dynamicStates/validate/false',

                              'dataType':'json',

                              'complete:function(data) {

                                            $("#div_state").html(data["div_state"]);

                                            $("#div_province").attr("style", data["div_province_style"]);

                                        },

                              'cache':false,

                              'data':jQuery(this).parents("form").serialize()});return false;

                }

   );


   $('#customer-form').yiiactiveform(

   {'attributes':[{'inputID':'Customer_first_name','errorID':'Customer_first_name_em_','status':1},{'inputID':'Customer_last_name','errorID':'Customer_last_name_em_','status':1},{'inputID':'Customer_login','errorID':'Customer_login_em_','status':1},{'inputID':'Customer_newPassword','errorID':'Customer_newPassword_em_','status':1},{'inputID':'Customer_company','errorID':'Customer_company_em_','status':1},{'inputID':'Customer_address','errorID':'Customer_address_em_','status':1},{'inputID':'Customer_city','errorID':'Customer_city_em_','status':1},{'inputID':'Customer_country_id','errorID':'Customer_country_id_em_','status':1},{'inputID':'Customer_state_id','errorID':'Customer_state_id_em_','status':1},{'inputID':'Customer_province','errorID':'Customer_province_em_','status':1},{'inputID':'Customer_zip_code','errorID':'Customer_zip_code_em_','status':1},{'inputID':'Customer_email','errorID':'Customer_email_em_','status':1},{'inputID':'Customer_phone','errorID':'Customer_phone_em_','status':1},{'inputID':'Customer_status','errorID':'Customer_status_em_','status':1},{'inputID':'Customer_referral_type_id','errorID':'Customer_referral_type_id_em_','status':1},{'inputID':'Customer_referral_notes','errorID':'Customer_referral_notes_em_','status':1},{'inputID':'Customer_is_good','errorID':'Customer_is_good_em_','status':1}],'summaryID':'customer-form_es_'});

});

/*]]>*/

</script>



Thanks again for your help!

Emily

I think that CActiveForm ajax validation calls the actionUpdate… because you set ‘enableAjaxValidation’=true…

Hi Mdomba,

Thanks. That was an interesting idea, but, alas, it did not turn out to be true.

Setting enableAjaxValidation to false means that:

a) NO ajax validation is called, even when the user is entering other form inputs,

e.g., the first_name input. This is NOT what I want; I love the ajax validation

for other form inputs.

B) actionUpdate STILL gets called

(I tested by putting a "print-to-log-file" statement in actionUpdate().)

If you have any ideas, they’re most welcome!

Best,

Emily

Figured it out!

enableAjaxValidation simply has to be overridden when calling the error() function

for the country_id element:




// In the _form.php view for customer: 

// This overrides ajax validation--turning it OFF when user selects a country from the dropdown. 

// Ajax validation remains ON for all other form elements, hooray! 

$enableAjaxValidation=false;

echo $form->error($model,'country_id', $htmlOptions=array(), $enableAjaxValidation); 



Thanks again for your help. Your comments led me toward the path of righteousness.

Emily

Well done! That was actually a lot easier than we all thought - just nobody else noticed it! :)

:mellow:

You said it. I thought this would require magic when in fact it required understanding how the error() function works!

I have an additional question since we are on this topic. When I am filling out a form of a create action and ajax validation is true and when filling out value for field1 the application validates field1…next when I fill out the value for field 2 the app validates field2… very nice so far. If however I set the ajax validation to true for the update action the result is that after I fill out value for field1 the application automatically validates the rest of the fields and colours them all. I wonder if anybody else has seen this and if there is already a work around this behaviour. Ideally I would like to have the application to validate only the field that value has been entered for…in other words the application should be validating the form fields one by one as value is being entered for each field just like in the actionCreate case.

Cheers,

bettor

Dear Emily,

I would be nice and very hardly to be able to find posts/thoughts like the ones you have given to this thread.

With you mind of thinking, I beg on your skill to write a very very good book which is surely to be super-easy to understand for readers.

I would be nice to see you around Emily Dickinson. Share with your thoughful working/thinking style!

Cheers!

Nam,

That’s a compliment. However, no time to write a book, when so much code needs to be written. I’m just happy to contribute here on the forum.

Enjoy Yii, dude!

:mellow: