[EXTENSION] Javascript form Validation

Hi zilchman,

you’re doing nothing wrong and I could reproduce the issue easily … now how to fix it is not so easy.

After some research I found that the Validate JQuery plugin that is used by the jformvalidate extension, overloads the Delegate method and this seems to prevent your own handler to be called when the dropDownList selection is changed by the user.

…so no ajax call is made.

This is what is found at the end of js/jquery.validate.js :




.....	

$.extend($.fn, {

		delegate: function(type, delegate, handler) {

			return this.bind(type, function(event) {

				var target = $(event.target);

				if (target.is(delegate)) {

					return handler.apply(target, arguments);

				}

			});

		},

		// ....

	});

})(jQuery); 

Now if you comment this delegate overloads, the ajax call is correctly done when selection changes. However this has some bad effects on other features : for instance validation does not occur anymore when a control lost the focus (but as you are using onfocusout = false this should not impact you).

Commenting a piece of code to solve a problem is not a good idea, but right now let’s say that it’s an acceptable workaround. I’ll try to find a better way to fix that, but it may take some times because I’m not a js expert.

Hope it helped anyway …

Thanks for the quick reply. At least I know what is going on now. I’ll Try your suggestion.

I have a few suggestions for the code.

  1. In the latest version of Yii, forms are generated by a form widget (CActiveForm) which requires you to make a lot of typing changes to switch over to using EHtml:: from $form->textField since some stuff has get labeled with active first and some doesn’t. So I made a copy of the Yii CActiveForm widget and renamed it ActiveForm. Since it is already just a mapping to the CHtml class, changing it to map to EHtml was trivial with find and replace. However, I’m not sure if this becomes rather inefficient since we are now mapping a widget to EHtml to CHtml. The only other change I made was to disable to ability to have AJAX form validation in the ActiveForm widget. See my attached code. 1124

ActiveForm.php

  1. I upgraded the validate plugin to the latest version (1.7) with no issues.

  2. I added a bit of code to warn people on leaving the page.

The changes for that were:

In: EJFValidate.php

Add:


                $options['submitHandler'] = "function(form) {

                        changed=false;

                        return true;

                   }";

Below:


	protected function prepareOptions(){


		$options = array_merge($this->pluginOptions, $this->_pluginOptions);

Add:


$js = 'var changed=false;

                                    function goodbye(e) {

                                        if (changed) {

                                            if(!e) e = window.event;

                                            //e.cancelBubble is supported by IE - this will kill the bubbling process.

                                            e.cancelBubble = true;

                                            e.returnValue = \'You will lose changes if you leave this page, please press Cancel to stay on this page and save your changes.\';

                                            //This is displayed on the dialog


                                            //e.stopPropagation works in Firefox.

                                            if (e.stopPropagation) {

                                              e.stopPropagation();

                                              e.preventDefault();

                                            }

                                       }

                                    }

                                   window.onbeforeunload=goodbye;';

                                Yii::app()->clientScript->registerScript('JValidatechanged', $js, CClientScript::POS_END);

                                $js = '                                    $("#'.$this->_formId . ' :input").change(function() {

                                      changed=true;

                                    });';

                                Yii::app()->clientScript->registerScript($this->_formId.'changed', $js, CClientScript::POS_END);

Below:


Yii::app()->clientScript->registerScript($this->_formId, $this->prepareOptions());

In: Jquery.validate.js

Change:


					if ( validator.settings.submitHandler ) {

						if (validator.submitButton) {

							// insert a hidden input as a replacement for the missing submit button

							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);

						}

						validator.settings.submitHandler.call( validator, validator.currentForm );

						if (validator.submitButton) {

							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced

							hidden.remove();

						}

						return false;

					}

					return true;



to:


					if ( validator.settings.submitHandler ) {

						if (validator.submitButton) {

							// insert a hidden input as a replacement for the missing submit button

							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);

						}

						submitReturn = validator.settings.submitHandler.call( validator, validator.currentForm );

						if (validator.submitButton) {

							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced

							hidden.remove();

						}

                                                if (submitReturn === true) {

                                                    return true;

                                                } else {

                                                    return false;

                                                }

					}

					return true;

I know a few of these changes are not the best for all since the first change will prevent people from using AJAX submit scripts, and it requires changing the jquery validate code. (Though I think using a bit of magic it should be possible to just add changed=false into a user specified function or code which is all my code needs to prevent a warning on submit.) I will submit a request to the validate plugin for a change similar to what I made to the JS. I did not prepend anything to my changed variable since that is one time code for the page and will register a change in any form. If you change two forms and submit one, the code will let that happen and you will lose your changes in the other form.

I’m happy to provide explanations for things if you have any questions.

Hi Loren,

and thanks for posting.

You’re right, about using CactiveForm to generate forms, and in fact I’ve already made some test in the direction you’re pointing … and it seems to work fine, with minimal adaptation effort (basically use something like JVFActiveForm instead of CActiveForm). Actually i had posted about that topic (see above) and the class you have attached is exactly what I planned to release … cool

Now regarding the ‘leaving page…’ feature it’s indeed very intresting but as you mentioned, having to modify the Validate JS plugin is a problem (hopefully, authors will include your changes).

Anyway, good job and thanks again for your clear explanation. I’ll release a new version that includes the ActiveForm class as soon as I have sometime …

bye

ps: if you’re using the extension on a website, I would be intresting to see it in action…

I assume you are wanting to see the page leave warning part live?

If that is what you are looking for, I will need to put a copy of our sandbox software live online somewhere which I’ve been meaning to do for a while so just let me know on that part.

I missed part of the documentation about jquery validate.

It works fine if you use:


            	$options['submitHandler'] = "function(form) {

                    	changed=false;

                    	form.submit();

               	}";

I had used this.submit() when I tried it the first time which creates an infinite loop instead of the correct form.submit()

yep, the “page leave” part would be nice to have a look at, but if it can’t be accessed on the web, don’t bother … you probably have something more urgent to do

bye

I will get my app online sometime in the next week.

I’ve had a few people in my organization ask to be able to play with the development version so it is just a matter of my making time to get it online (and replace all the data with fake data…)

Here is one more change to implement the length is validation: (I use the rangelength validation rule to implement it.)

In EJFValidate.php:

Find:


		elseif($ruleName == 'length')

		{

			// This rule has no direct equivalent in the plugin, it must be splited

			// into 2 JS rules : min and max

			

			if( isset($ruleParams['min']) ) {

				$this->_rules[$attrActiveName]['minlength'] = $ruleParams['min'];

				$this->addValidatorMessage($attrName,$attrActiveName,'minlength',$ruleParams);

			}	

			if( isset($ruleParams['max'])) {

				$this->_rules[$attrActiveName]['maxlength'] = $ruleParams['max'];

				$this->addValidatorMessage($attrName,$attrActiveName,'maxlength',$ruleParams);

			}

Replace With:


		elseif($ruleName == 'length')

		{

			// This rule has no direct equivalent in the plugin, it must be splited

			// into 2 JS rules : min, max, and is

			

			if( isset($ruleParams['min']) ) {

				$this->_rules[$attrActiveName]['minlength'] = $ruleParams['min'];

				$this->addValidatorMessage($attrName,$attrActiveName,'minlength',$ruleParams);

			}	

			if( isset($ruleParams['max'])) {

				$this->_rules[$attrActiveName]['maxlength'] = $ruleParams['max'];

				$this->addValidatorMessage($attrName,$attrActiveName,'maxlength',$ruleParams);

			}

                    	if( isset($ruleParams['is'])) {

				$this->_rules[$attrActiveName]['rangelength'] = array($ruleParams['is'],$ruleParams['is']);

				$this->addValidatorMessage($attrName,$attrActiveName,'rangelength',$ruleParams);

                    	}

Find:


				'minlength' => Yii::t('yii','{attribute} is too small (minimum is {min}).'),

				'maxlength' => Yii::t('yii','{attribute} is too big (maximum is {max}).'),

Add Below:


                            	'rangelength' => Yii::t('yii','{attribute} is of the wrong length (should be {is} characters).'),

I used to write modifications for Invision Power Board which resulted in writing lots of manuals on how to properly edit the code so that is where my code changes style comes from.

Hi, I just started to use jformvalidate extension. After some attempts, I can display and submit the form data correctly with EHtml form elements. However I can’t get the checkboxlist retain their status after clicking the submit button. I can run the sample testForm in my workspace. One thing I noticed is the name value of the hidden field generated with the js lacking of the prefix: “EJSv_”. For example, in testForm 4, the hidden field is generated as:




<input type="hidden" name="EJSv_TestForm[favcolor]" value="" id="ytTestForm_favcolor">



but in my case, the hidden field is:




<input type="hidden" name="AddAdminForm[select_pub]" value="" id="ytAddAdminForm_select_pub">



I suspect this is the reason why the checkboxlist can’t retain the value selected before form submit. But I have tried every method which I can think of, still no idea where went wrong. I even copied the view from the sample code. I have been struggling with the problem for a few days, can anyone help me out of it? Thanks.

hi kuanfai,

if the prefix is not set for the checkbox element it is indeed a problem that can cause the extension to not work correctly. Yes, please, copy & paste the code of your form and I’ll try to reproduce this strange behavior … and possibly fix it (if its a bug ;) )

regards

8)

[center]

[/center]

[left]Hi all,[/left]

as you may already know, the latest release (1.1.7) of our favorite framework now includes client-side form validation feature. The powerful CActiveForm core widget now comes with a enableClientValidation option that enables you to benefit from this feature, with no additional effort.

You can find more information in the v1.1.7 release notes, and in the API documentation.

Consequently, as you may imagine, there is no need for another extension that would provide same features, and therefore, the jformvalidate extension has reached its end. With more than 2800 downloads, I like to think it has been useful to some of you, and the feedback I received sometime, tend to confirm that all the time I spent on this extension was not wasted.

For those who are still using it, I’ll do my best to provide support, however, in the future I don’t plan to release a new version of this extension (that would include CActiveForm support… this is now done in 1.1.7 ! ).

[size="3"]Again, thanks to all of you who participated in improving this extension by suggesting changes, pointing out and even sometimes fixing bugs…[/size]

[size=“3”][color="#0000FF"]… Let’s say bye bye to jformvalidate and a big welcome to 1.1.7 CActiveForm !![/color][/size]

ciao

8)