How to bind 2nd function to the jQuery validation submitHandler - javascript

How would I add additional functionality to the jQuery validation submitHandler that is set in another script? I cannot modify the source JavaScript that is defining the submitHandler in the first place. Instead, I need to add some additional functionality to it from a subsequent script that runs. Here is some scaled-down pseudo-code for the .js file that is defining the submitHandler in the first place--which I cannot directly modify:
$("#frmReg").validate({
invalidHandler: function(e, validator) { //code here ... not relevant },
submitHandler: function() {
window.onbeforeunload = null;
$('#myForm')[0].submit();
},
rules: { firstname: { required: true } },
messages: { firstname: { required: 'First name is required' } }
});
Essentially, I want to bind a second function to the existing submitHander.

I glanced over the source and I think this should work:
var validatorInstance = $("#frmReg").validate(), //Call this AFTER the initial registration,
submitHandler = validatorInstance.settings.submitHandler;
validatorInstance.settings.submitHandler = function(){
//Do your custom stuff here
console.log(true);
return submitHandler.apply(this,arguments); //forward to the old handler
};

Related

Jquery Validation dynamic inputs [duplicate]

I have a form on which I am using jquery.validate. I initially call validate with a set of rules and custom messages...
$("#formName").validate( {
rules: {
myExistingInput: {
required: true
}
},
messages: {
myExistingInput: {
required: "Enter something"
}
},
ignore: null, // include hidden fields (see below)
submitHandler: function(form) {
// do stuff
},
invalidHandler: function(event, validator) {
// do stuff (some of the fields may have been hidden by a collapsible panel
// if there is an error on one of those fields, expand the panel so the error
// becomes visible)
}
});
Later, I dynamically add fields to the form, and add rules for those fields too...
$("#formName").append(...);
$("#newInputName").rules("add", {
required: true,
messages: {
required: "Enter something else"
}
});
If I then submit the form, I get an error from within jquery.validate...
Exception occured when checking element newInputName, check the
'messages' method.TypeError: Unable to get property 'call' of
undefined or null reference
Debugging in the browser, I can see the error is being thrown from within the "check" function, and that the "method" variable is set to "messages".
If I remove the messages from the call to rules("add",...
$("#newInputName").rules("add", {
required: true
});
it works as expected, but obviously I now have no custom error messages.
I have seen many examples here on SO indicating that my syntax is correct. Any suggestions?
BTW: jQuery Validation Plugin - v1.11.0 - 2/4/2013
Your code seems to be working, without error, as you posted it.
DEMO with DOM ready: http://jsfiddle.net/UZTnE/
DEMO with PageInit & jQuery Mobile: http://jsfiddle.net/xJ3E2/
$(document).on("pageinit", function () {
$('#myform').validate({ // initialize the plugin
rules: {
field1: {
required: true
}
},
messages: {
field1: {
required: "Enter something"
}
}
});
$('[name*="field"]').each(function () {
$(this).rules('add', {
required: true,
messages: {
required: "Enter something else"
}
});
});
});
HTML:
<form id="myform">
<input type="text" name="field1" />
<input type="text" name="field2" />
<input type="submit" />
</form>
BTW:
this...
ignore: null, // include hidden fields
should be...
ignore: [], // include hidden fields
See: jQuery Validate - Enable validation for hidden fields
$(document).ready(function(){
$("#controlId").rules("add", {
required : true,
messages : { required : 'field is required.' }
});
});
as an answer to this old issue, I do like this to get the meassges inside the rules object.
After you have added the rules you can add messages like this:
var inputRules = $('input').rules();
inputRules.messages = {required: 'your message'};
Good luck!

jQuery validator does not trigger before I hit enter or submit

I'm trying to implement jQuery Validation Plugin v1.19.2 (http://jqueryvalidation.org/), it doesn't trigger automatically at first. It only activates afterI I hit enter or submit the form. Once I have hit enter or submit form then it works on keyup.
Please see following gif to understand what I mean. The first field (title) is required, as you can see that I enter text there, and then delete a few times but it does not show any error. But after I submit, then each time it shows error.
Here's the JSFiddle link: http://jsfiddle.net/ubwq95e8/
$(document).ready(function() {
$("form#signup").validate({
rules: {
title: {
required: true
},
},
});
});
Try to add onkeyup in $("form#signup").validate.
See document: https://jqueryvalidation.org/validate/#onkeyup
onkeyup: function(element) {
$(element).valid();
},
The plugin doesn't validate on onkeyup event by default, you need to implement it as per your requirements. Here's a simple example:
$("form#signup").validate({
onkeyup: function (element, event) {
$(element).valid();
},
rules: {
title: {
required: true
},
},
errorPlacement: function(error, element){}
});
Similarly for other event like onclick, onfocus* etc
just add a custom event for check inputs when focusout
$(document).ready(function() {
$("form#signup").validate({
rules: {
title: {
required: true
},
},
errorPlacement: function(error, element){}
});
$('#signup input').focusout(function(){
var form = $( "#signup" );
form.valid()
})
});
here is new jsfiddle with codes that work for your case
http://jsfiddle.net/qhsj84en/

Two onmouseout events doing the same action on their respective elements

I have a script which validates the inputs entered upon an onmouseout event. Firstly when the user move the cursor away from the first input, the validation occurs and the error message is shown. I want to do the same process with the second input, that is, an error message is shown when the cursor is moved away from the second input. Below is my code:
<script type="text/javascript">
$('document').ready(function () {
$('#Make').on('mouseout', function () {
$("#carform").validate({
rules: {
Make: {
required: true
}
},
messages: {
Make: {
required: "Please enter a make"
}
},
submitHandler: function (form) {
form.submit();
}
});
if ($("#carform").valid()) {
//Do some code
}
});
$('#Model').on('mouseout', function () {
$("#carform").validate({
rules: {
Model: {
required: true
}
},
messages: {
Model: {
required: "Please enter a model"
}
},
submitHandler: function (form) {
form.submit();
}
});
if ($("#carform").valid()) {
//Do some code
}
});
});
</script>
My view:
<div>
<form id="carform" method="post">
<p>
#Html.LabelFor(l=>l.Make)
#Html.TextBoxFor(l => l.Make)
</p>
<p>
#Html.LabelFor(l=>l.Model)
#Html.TextBoxFor(l => l.Model)
</p>
<p>
<input id="createCar" type="submit" value="Submit"/>
</p>
</form>
</div>
When I move my cursor away from the input Make, the error message is seen. But when I do the same with the second input Model, no error message is seen. Any idea where I am doing it wrong?
You just need to initialize it once.. Not on each input blur and you have option in jquery validation which validates on blur which is as below:
onfocusout
Type: Boolean or Function()
Validate elements (except checkboxes/radio buttons) on blur. If
nothing is entered, all rules are skipped, except when the field was
already marked as invalid.
Set to a Function to decide for yourself when to run validation.
A boolean true is not a valid value.
Example: Disables onblur validation.
$(".selector").validate({
onfocusout: false //Do not use false instead use a callback function
});
The callback gets passed two arguments:
element
Type: Element The element currently being validated, as a DOMElement.
event
Type: Event The event object for this focusout event.
So you can make use of callback function as below in your case:
$('document').ready(function () {
$("#carform").validate({
onfocusout: function(element) {
this.element(element);
},
rules: {
Make: {
required: true
},
Model: {
required: true //keep both the required here
}
},
messages: {
Make: {
required: "Please enter a make"
},
Model: {
required: "Please enter a model" //keep both the messages here
}
},
submitHandler: function (form) {
if ($(form).valid()) { //check for valid form here
form.submit()//submit here
}
}
});
$('#Make,#Model').on('blur', function() {
$("#carform").validate().element( this );
});
});
Simple, define a same class for both inputs say class foo
and check mouseout event with class as an identifier like:
$('.foo').on('mouseout', function () {
// your code here
});

POST information to 2 areas. PHP / Javascript

Just wondering if you can try and assist.
I have a register form in WordPress that is being posted to a user database. I also need to pass the same form information to a webhook (Zapier).
I understand you cannot have 2 form action's for one form however I ideally need to find the best way of submitting both sets of information; one to the database and one to the webhook link.
An example of my code posting to my database. I need this to also post to
https://zapier.com/examplehook/
<form name="register_form" id="register_form<?php $template->the_instance(); ?>" action="$template->the_action_url( 'save-register' ); ?>" method="post”>
I was thinking of possibly using an onclick event to run a javascript function that also does a simultaneous form action. I'm confused if that would work though.
//edited code
$('#registerform').validate({ // initialize the plugin
rules: {
first_name: {
required: true
},
last_name: {
required: true
},
user_email: {
required: true,
email: true
},
user_login: {
required: true
},
hear_about_us: {
required: true
},
contact_number: {
required: true
},
address:{
required: true
},
post_code: {
required: true
}
},
submitHandler: function (form) {
$('#registerform').on('submit', function(event) {
event.preventDefault();
var xhr1 = $(this).ajaxSubmit({url: 'https://zapier.com/example-hook/'}).data('jqxhr');
var xhr2 = $(this).ajaxSubmit({url: '/register/'}).data('jqxhr');
$.when(xhr1, xhr2).then(function() {
window.location.replace("/register-step2/");
}, function() {
// error occured
});
});
}
});
Any suggestions would be ideal!
Thanks
You can use Jquery Form Plugin for this:
$('form').on('submit', function(event) {
event.preventDefault();
var xhr1 = $(this).ajaxSubmit({url: 'http://firsturl'}).data('jqxhr');
var xhr2 = $(this).ajaxSubmit({url: 'http://secondurl'}).data('jqxhr');
$.when(xhr1, xhr2).then(function() {
// both submits succeeded, redirect
}, function() {
// error occured
});
});

JQuery Validate is firing both Highlight and Unhighlight in Chrome

I am having a really strange problem with Jquery validate that only occurs in Chrome. The validation on this page seems to be firing both the Highlight and the Unhighlight functions in the .validate() function so if I dont fill out the form it cycles through each element and applies the "invalid" class in the highlight function but then for some reason it goes through and immediately applies the code in unhighlight and I cant work out why?
JS
$(document).ready(function () {
//Validation for form fields on Payment form
/*This adds a method to test whether value is equal to placeholder, and if it is, don't consider it filled out. This is necessary to circumvent IE placeholder plugin*/
jQuery.validator.addMethod("notEqual", function (value, element, param) {
return this.optional(element) || value != param;
}, "Required.");
$('#payment-form').validate({
onfocusout: function (element) {
$(element).valid();
},
rules: {
"data[Payment][card_holder]": { required: true, minlength: 2 },
"data[Payment][card_number]": { required: true, creditcard: true },
"data[User][first_name]": { required: true, notEqual: "First Name" },
"data[User][last_name]": { required: true, notEqual: "Last Name" },
"data[UserDetail][company]": { required: true },
"data[UserDetail][job_title]": { required: true },
"data[UserDetail][telephone]": { required: true },
"data[User][email]": {
required: true,
email: true,
remote: {
url: "/usermgmt/users/email_exists",
type: "post"
}
},
"data[User][password]": { required: true },
"data[Address][billing_line_1]": { required: true },
"data[Address][billing_line_2]": { required: true },
"data[Address][billing_state]": { required: true },
"data[Address][billing_postcode]": { required: true },
credit_exp_month: { required: true, notEqual: "MM", number: true, max: 12, minlength: 2, maxlength: 2 },
credit_exp_year: { required: true, notEqual: "YYYY", number: true, minlength: 2, maxlength: 4 },
"data[Payment][cvv]": { required: true, number: true, minlength: 3, maxlength: 4 },
},
errorClass: 'error',
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass(errorClass).addClass(validClass);
validateIcon(element);
},
highlight: function (element, errorClass, validClass) {
$(element).addClass(errorClass).removeClass(validClass);
validateIcon(element);
}
});
function validateIcon(element) {
$(element).siblings('span.validate_icon').remove();
if ($(element).hasClass('error')) {
alert("error");
$(element).closest('li').find('label>span:first').html('<span class="validate_icon invalid"> <span class="icon-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-exclamation"></i></span></span>');
} else if ($(element).hasClass('valid')) {
alert("valid");
$(element).closest('li').find('label>span:first').html('<span class="validate_icon valid"> <span class="icon-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-ok"></i></span></span>');
}
}
});
PHP Code that handles the email exists:
public function email_exists() {
$this->autoRender = false;
if($this->request->is('post')) {
$this->RequestHandler->respondAs('json');
if(!$this->User->findByEmail($this->request->data['User']['email'])) {
echo json_encode(true);
} else {
echo json_encode(false);
}
}
}
I have also tried simply echo "true"; and echo 1; I have tried everything suggested in the comments below but regardless - the problem exists.
I had the exact same problem, and by seeing your code I might say that you have the same cause, but let's break it down.
Checking
First, let's check that my comment is relevant, and I can actually help you. Comment the remote param on your email validation set up:
"data[User][email]": {
required: true,
email: true
},
Is your problem fixed? Great, keep reading (feel free to skip to the fix section).
The problem
1. When the plugin validates, it creates a list of errors, stored into an array called "errorList".
2. Have you ever used the showErrors functionality? It's there to show all the errors, but also to target-show errors. If you want to show specific errors, or to show errors that are out of the limits of the plugin (ej.: a 60s timeout has expired), you can use that method.
3. When showing specific errors, what that method does is to add the specified error(s) to the errorList.
4. The problem is that before adding new errors that list is cleared up (I didn't write the code, but it seems that it's done in order to keep that list nice and clean, and not having two different errors of the same input).
5. Now, when the email is checked remotely we are in the same situation of a timeout. So it uses the showErrors functionality, and that means that the form is validated when click, and some seconds later (with the PHP response), the email error is shown, but clearing up the errorList. That's what is happening.
The fix
If you are not going to do explicit use of showErrors, truth is that you can comment the line where the errorList is cleared up:
showErrors: function( errors ) {
if ( errors ) {
// add items to error list and map
$.extend( this.errorMap, errors );
//this.errorList = [];
for ( var name in errors ) {
...
If you are going to do an explicit use of that method, you can try this version instead. Doesn't clear the error list, but checks that you're not adding the same error twice:
showErrors: function( errors ) {
if ( errors ) {
// add items to error list and map
$.extend( this.errorMap, errors );
for ( var name in errors ) {
var tempElem = this.findByName(name)[0];
this.errorList = jQuery.grep(this.errorList, function( error, i ) {
return error.element != tempElem;
});
this.errorList.push({
message: errors[name],
element: tempElem
});
}
Let me know if worked or you have any problem.
This code of yours can be a problem...
onfocusout: function (element) {
$(element).valid();
},
You cannot put the .valid() method inside of the .validate() method without causing some serious issues.
This is the default onfocusout function from the plugin...
onfocusout: function( element, event ) {
if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
this.element(element);
}
}
What's the purpose of your custom onfocusout function? Generally, it's not needed since the onfocusout trigger is already built into the functionality. One constructs their own onfocusout function only to over-ride the built-in default. So if you want the default onfocusout behavior, just remove the onfocusout option entirely.
If you really want to emulate something like in your code, it would need to look like this...
onfocusout: function(element, event) {
this.element(element);
}
Quote OP Comment:
"as I said im not really sure what good it would do you: (I cant get it to format here..)"
$this->RequestHandler->respondAs('json');
if(!$this->User->findByEmail($this->request->data['User']['email'])) {
return json_encode(true);
} else {
return json_encode(false);
}
It does a lot of good to show any code that could be affecting the problem, especially any code that's wrong. This could have been solved two days ago.
return is for returning to the PHP function that called this one. In other words, return will do nothing here since there is no PHP function to return to. On the other hand, echo will output from PHP... and that's what you need for jQuery Validate remote...
if (....) {
echo true;
} else {
echo false;
}
PHP return versus PHP echo
Also see: https://stackoverflow.com/a/21313309/594235

Categories