beforValidate not working anymore to prevent validateOnSubmit?

Hi, I have this code binded to the clientOptions.beforeValidate in an CActiveForm configure with clientValidation, in order to prevent validation when a secondary button is pressed:

In PHP view:


   <?php

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

 		'id'=>'alias-form',

 		'enableClientValidation'=>true,

 		'enableAjaxValidation'=>true,

 		'errorMessageCssClass'=>'clsErrorMessage',

 		'clientOptions'=>array(

        	'validateOnSubmit'=>true,

        	'validateOnChange'=>false,

        	'errorCssClass'=>'clsError',

        	'successCssClass'=>'clsSuccess',

        	'validatingCssClass'=>'clsValidating',

        	'beforeValidate'=>"js:beforeValidate",

 		),

  	));

   ?>

Javascript code:


function beforeValidate(form) {

   if (form.data('submitObject') && form.data('submitObject')[0].name == 'cancel') {

  	this.validateOnSubmit = false;

  	this.validateOnChange = false;

  	this.beforeValidate = ''; // the problem is caused by this line

  	form.submit();

  	return false;

   }

   else {

  	return true;

   }

}

This used to work, but now I get this js error:

That line reads:


if(settings.beforeValidate==undefined || settings.beforeValidate($form)) {

What can be done to fix this? Thanks in advanced.

maybe to give a function to beforeValidate like


'beforeValidate'=>"js:beforeValidate()",

And note that your function beforeValidate() expects one parameter… so you need to send even that parameter to it…

How did this work before? Do you still have that code?

Thanks, but the problem is not in the PHP code but in the Javascript code. The [font="Arial"]code that was working is exactly the one I posted. The[/font] objetive of that code is to avoid client (javascript) validation on form submit, so I can have two submit buttons in the same CActiveForm, for instance, one for save and one for cancel, and in case the cancel button is pressed, no validation is triggered on submit. That would be similar to the [font="Courier New"]CausesValidation [/font]switch in Prado.

Is there any way to emulate this [font="Courier New"]CausesValidation="false" [/font]for client side validation?

P.S. for server side validation there’s no problem since I check $_POST[‘cancel’] to see if the cancel but was pressed.

P.P.S. my original post: http://www.yiiframew…-cancel-button/

P.P.P.S. now that I remember, even the original code could be causing the problem, since I didn’t tried the page with MSIE before (and MSIE is more strict when reporting JS errors)

Added a feature request: http://www.yiiframework.com/forum/index.php?/topic/22979-avoiding-client-side-validation-on-secondary-submit-buttons/

??

I think that


'beforeValidate'=>"js:beforeValidate",

is quite legal according to the reference.

http://www.yiiframework.com/doc/api/1.1/CActiveForm/#clientOptions-detail

The code like the following is working fine for me.




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

	array(

		'id'=>'event-member-form',

		'enableAjaxValidation' => true,

		'clientOptions' => array(

			'validateOnSubmit' => true,

			'beforeValidate' => 'js:beforeValidate',

		),

	)

);

$js = <<< EOS

function beforeValidate(form) {

	if ( form.data('submitObject') && btn[0].id == 'cancel_btn' ) {

		this.validateOnSubmit = false;

		this.beforeValidate = '';

		form.submit();

		return false;

	}

	return true;

}

EOS;

Yii::app()->clientScript->registerScript('event-member-form-beforeValidate', $js);



Are you 100% sure? Have you tried with MSIE with js debugging turned on? I have the same code and the error is thrown on submit, because [font=“Courier New”]this.beforeValis a js error in Yii’s validation code, no further js is executed and the form is sent without validation.

Weird, now it worked commenting this line out:


// this.beforeValidate = ''; 

Anyway, my feature request is still open, since it would be easier to have the code integrated into CActiveForm…

I correct myself. Doing this will result in the beforeValidate function being called an infinitum. In Firefox the execution will halt and the form will be submitted, in MSIE the recursion will freeze the browser. So, don’t do it :)

Ok, I made a quick hack patch to CActiveForm, please check "my feature request" post (linked above).

Yeah, you are right. I didn’t notice that the error was ignored in Chrome.

OK, I’ve debugged my code and confirmed the error.

The code in my original post has an error.




$js = "function beforeValidate(form) {

-    if ( form.data('submitObject') {

+    if ( form.data('submitObject') ){

        this.validateOnSubmit = false;

        this.beforeValidate = '';

        form.submit();

        return false;

    }

    return true;

}";



It just checks whether the submission (and validation) is caused by clicking any button. When you hit Enter key, “form.data(‘submitObject’)” returns undefined.

And the code of the previous post has an error, too.




function beforeValidate(form) {

-       if ( form.data('submitObject') && btn[0].id == 'cancel_btn' ) {

+       var obj = form.data('submitObject');

+       if ( obj && obj[0].id == 'cancel_btn' ) {

                this.validateOnSubmit = false;

                this.beforeValidate = '';

                form.submit();

                return false;

        }

        return true;

}



It checks the button’s ID.

I don’t remember why I used “btn[0]”. What is it? :(

But there’s still an error, with this:


this.beforeValidate = '';

The core Yii’s javascript validation code will throw an error.

Try this code, it should work, I added this code directly to CActiveForm as a patch, but I still need to fix it since the function name "beforeValidate": could clash with another existing function:


function beforeValidate(form) {

   if (form.data('submitObject')) {

  	if (form.data('submitObject')[0].name in {$buttons}) {

     	this.validateOnSubmit = false;

     	this.beforeValidate = function beforeValidate(form) { form.submit(); };

     	form.submit();

     	return false;

  	}

   }

   return true;

}

Also this.[font="Courier New"]beforeValidate = function beforeValidate(form) { form.submit(); };[/font] is a very dirty hack, but without something like that the whole thing will fail.

Ok, I forgot it, since you’re including js directly, in this line:

<br><br>


if (form.data('submitObject')[0].name in {$buttons}) {

<br><br>replace [font=“Courier New”]{$buttons}[/font] with a javascript array like [font=“Courier New”]{‘cancel’:’’}[/font]

But why to you submit again the form from the submit handler ?

The beforeSubmit function is expected to return true or false… so you just test if the button pressed is your CANCEL button and in that case return false…

without any other settings or submitting…

Not beforeSubmit but beforeValidate.

We know that validation and submitting will be canceled when beforeValidate returns false.

What we want is submitting without validation when Cancel button is clicked.

I see…

The main “problem” is that you want to SUBMIT the form… but why submit the form if that is a CANCEL button and you don’t need the data?

Yes, canceling of the form input can be achieved by a simple link.

Or, further more, some users may not need a cancel link at all. They can just go back where they have been. … just as we see in the post form of this forum.

I agree that there’s no technical reason to implement the canceling by submitting.

But I want a pair of buttons side by side in the last row of my form: "Submit" (or "OK", "Send", "Update", …etc) and "Cancel". The two buttons should look equally important to the user. I want to let the users know explicitly that they can cancel the form.

[EDIT]

Maybe this is due to the fact that I’ve been working with the Windows modal dialogs for a very long time.

Ah, you are right. I’ve confirmed it, too.

And by reading the jquery.yiiactiveform.js, I agree with you that there’s no easy workaround without touching the core codes …

"Cancel" is just a label. It could be anything, for example "Delete", "Find postal code", etc. which launches a server side action, like the [font="Courier New"]OnCommand[/font] handler in Prado.

When you click ‘Cancel’ you don’t submit the form. I do this:


                	<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>

                	<?php echo CHtml::Button('Cancel', array('submit' => Yii::app()->request->getUrlReferrer())); ?>