Skip Navigation

[Resolved] Unable to Get Custom Javascript Validation to Work with Cred Form

This thread is resolved. Here is a description of the problem and solution.

Problem:

The issue here is that the user wanted to validate some of their form fields using jQuery

Solution:

This can be done by following the example in the link below.
http://form.guide/jquery/validation-using-jquery-examples.html

This should serve as a guide on how it can be done with our forms.

This support ticket is created 5 years, 5 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- 9:00 – 12:00 9:00 – 12:00 9:00 – 12:00 9:00 – 12:00 9:00 – 12:00 -
- 13:00 – 18:00 13:00 – 18:00 13:00 – 18:00 14:00 – 18:00 13:00 – 18:00 -

Supporter timezone: America/Jamaica (GMT-05:00)

This topic contains 15 replies, has 2 voices.

Last updated by Dave 5 years, 5 months ago.

Assisted by: Shane.

Author
Posts
#1274559

Tell us what you are trying to do?

Validate the user input in a text field without refreshing the page.

Is there any documentation that you are following?

I've tried a lot of different approaches to this, but a good example is here:

hidden link

Is there a similar example that we can see?

They also have a demo that will illustrate it:

hidden link

I have been trying to perform two simple checks on the user input in a single cred form field before the form is submitted and I am pulling my hair out at how ridiculously complicated it is turning out to be. To be fair I'm not very well versed in JS so it might just be me as much as anything else, but it appears that Toolset is lacking some simple functionality here.

I have a form that appears in a Bootstrap modal window that asks the user to enter a number so that we can track how many of a product they have purchased. This works very well with the flow of the site but I found out that the cred_form_validate hook ONLY works on refresh. This means that I can get it to work perfectly, but it is totally useless as a refresh closes the modal window and it will only show the error if you reopen the modal window.

So I have been trying to implement a live validation check to see if the number is zero or higher and still below the amount the customer originally requested, illustrated here in php:

function gift_number_validation($error_fields, $form_data) {
	
	//field data are field values and errors
    list($fields,$errors)=$error_fields;
	$purchasing = isset( $_POST['amount-purchased'] ); //$fields['wpcf-amount-purchased']['value'];
	$requested = get_post_meta( get_the_ID(), 'wpcf-gift-quantity', true);
	
	
	if ( $purchasing > $requested || $purchasing < 0 ) {
		//set error message for my_field
            $errors['wpcf-my_field'] = "Please enter a value between 0 and " . $requested;
	}
	
	//return result
    return array($fields,$errors);
}

I know that I will need to use Javascript to achieve this, as it is running in the browser, live; as such I have been trying to add code to the JS Script box on the cred form page, but nothing I have tried seems to work. My first solution was to try this:

jQuery( function($) {
  $("input[name='amount-purchased']").live('change');
  console.log("Change spotted");

  var purchased = document.getElementsByName("amount-purchased").value;
  var requested = document.getElementsByName("gift-quantity").value;
  var claimed = document.getElementsByName("quantity-claimed").value;
  var remaining = requested - claimed;
  //var purchase = purchased.options[purchased.selectedIndex].value;
  console.log("Amount = " + purchased);

  if( purchased > 0 ) {
    var message = "Please enter a positive number";
  } else if ( purchased > requested ) {
    var message = "Please enter a lower amount";
  } else if ( purchased > claimed ) {
    var message = "Please don't buy more than " + remaining;
  }

  if ( message != '' ) {
    alert( message );
  }
});

and this:

jQuery(document).ready
  jQuery( function($) {
    $("input[name='amount-purchased']").live('change', check);
    console.log("Change spotted");
  });

  function check($) {
  console.log("Jumped to function");  
  var purchased = /*$('select[name="amount-purchased"]'); */document.getElementsByName("amount-purchased");
  var requested = document.getElementsByName("gift-quantity").value;
  var claimed = document.getElementsByName("quantity-claimed").value;
  var remaining = requested - claimed;
    var purchase = purchased.options[purchased.selectedIndex].value;
    console.log(purchase);
    
//var $e = $('select[name="wpcf-booking-contract-type"]');
//var val = $e.val();    
    
    if( purchased > 0 ) {
      var message = "Please enter a positive number";
    } else if ( purchased > requested ) {
      var message = "Please enter a lower amount";
    } else if ( purchased > claimed ) {
      var message = "Please don't buy more than " + remaining;
    }

    if ( message != '' ) {
      alert( message );
    }
  }

as well as experimenting with other variations. But no matter what I do, the variables ALWAYS come back as undefined, even though this is executing after the DOM elements.

I have seen other posts about similar topics such as:

https://toolset.com/forums/topic/get-the-select-value-of-a-select-field-of-a-form-using-js/
https://toolset.com/forums/topic/make-an-operation-between-fields-on-cred-javascript/

But even attempting to implement their solutions has not helped. I have also attempted to integrate the jQuery Validation Plugin mentioned at the top (note: it is not a WordPress plugin, simply a jQuery one so the script requires enqueuing) but that produces similar results.

Here is the cred form:

[credform]
	[cred_field field='form_messages' class='alert alert-warning' id='number-bought']
	<div class="row number_layout v-centre">
      <div class="col-sm-6">Today I have bought:</div>
      <div class="col-sm-6">
        [cred_generic_field type='numeric' id='amount-purchased' field='amount-purchased']
            {
              "required":0,
              "validate_format":1,
              "default":"1"
            }
        [/cred_generic_field]
      </div>
      <span style="display: none;">[types field='gift-quantity' output='raw'][/types]</span>
      <span style="display: none;">[types field='quantity-claimed' output='raw'][/types]</span>
	</div>
	<br />
	<p class="centre"><strong>Warning:</strong> Please be accurate as incorrect purchasing information can result in the happy couple or other people missing out!</p>
	</div>
	<div class="modal-footer">
	[cred_field field='form_submit' output='bootstrap' value='Submit' class='btn right']
[/credform]

Please ignore any strange looking markup as it works together with another bit of code that calls it.

All I want to do is read the value of the "amount-purchased" field and check if it is between 0 and whatever value is held in "gift-quantity" after subtracting "quantity-claimed".

I'd really appreciate some help straightening this out and (unless I have completely missed it) I really think Cred needs some live validation options for the future.

Cheers.

I just want to read the value in the

#1274619

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Dave,

Thank you for contacting our support forum.

Is it possible for you to send me a link to the form on the frontend to check the field names that are actually being generated?

I suspect that this is the issue here.

Thanks,
Shane

#1274621
Field Rendering.png

It's a little convoluted to get to the exact form, but perhaps this screenshot will help clarify?

Although it does seem that the wpcf- fields are rendering a result not a field, but it still claims the 'amount-purchased' isn't defined.

If not just send me a private message and I'll sort you out with instructions.

#1274649

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Dave,

I suggest you start small by testing your code in the console.

For e.g what I would do is to paste this in my JS console on the frontend.

  var requested = document.getElementsByName("gift-quantity").value;

Then see what is returned, this way you can check to see if the right values are being returned for you code.

Thanks,
Shane

#1274657
Undefined.png

Hi Shane,

That is precisely what I have spent most of the day doing bud. No matter what I do, the Toolset fields are coming up as undefined. To follow your example, with this code in place:

jQuery(document).ready
  jQuery( function($) {
    $("input[name='amount-purchased']").live('change', check);
    console.log("Change spotted");
  });

  function check($) {
  console.log("Jumped to function");  
  var purchased = /*$('select[name="amount-purchased"]'); */document.getElementsByName("amount-purchased");
  var requested = document.getElementsByName("gift-quantity").value;
  var claimed = document.getElementsByName("quantity-claimed").value;
  var remaining = requested - claimed;
    var purchase = purchased.options[purchased.selectedIndex].value;
    console.log(purchase);
    
    if( purchased > 0 ) {
      var message = "Please enter a positive number";
    } else if ( purchased > requested ) {
      var message = "Please enter a lower amount";
    } else if ( purchased > claimed ) {
      var message = "Please don't buy more than " + remaining;
    }

    if ( message != '' ) {
      alert( message );
    }
  }

I get the results shown in the screen shot; Undefined. Which is driving me mad!

Any thoughts on why these variables are refusing to be defined? I'm guessing it has something to do with the DOM load sequence but that is purely a guess.

#1274673

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Dave,

The problem is most certainly not using the correct identifiers.

Try using jQuery to get the field values.

var val = jQuery("input[name=nameGoesHere]").val();

Thanks,
Shane

#1274675

I wouldn't be surprised, I feel like I've tried so many variations!

I'll test it out later when I get back home and let you know.

Cheers bud.

#1274767

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Dave,

Thanks, looking forward to hearing some good news on this.

Thanks,
Shane

#1274803

Cheers bud, that clue you gave me has pushed me down the right path. Here is my "working" code. It is validating correctly and the logic is sound, I just need to make it actually have an effect on the users ability to submit the field now.

jQuery(document).ready
  jQuery( function($) {
    $("input[name='amount-purchased']").live('change', check);
    console.log("Change spotted");
  });

  function check($) {
  console.log("Jumped to function");
    var purchased = jQuery("input[name=amount-purchased]").val();
    var requested = jQuery("input[name=wpcf-gift-quantity]").val();
    var claimed = jQuery("input[name=wpcf-quantity-claimed]").val();
    var remaining = requested - claimed;
    
    if( purchased < 0 ) {
      var message = "Please enter a positive number";
    } else if ( purchased != Math.floor( purchased ) ) {
      var message = "Please only enter whole numbers";    
    } else if ( purchased > remaining ) {
      var message = "Please don't buy more than " + remaining;
    } else if ( purchased == 0 ) {
      var message = "No gift updates will be made";
    }

    alert( message );
    var message;
  }

I also had to update the way that the custom fields were being rendered into the form so they are able to be referred to , not simply a raw number:

[credform]
	[cred_field field='form_messages' class='alert alert-warning' id='number-bought']
	<div class="row number_layout v-centre">
      <div class="col-sm-6">Today I have bought:</div>
      <div class="col-sm-6">
        [cred_generic_field type='numeric' id='amount-purchased' name="amountPurchased" field='amount-purchased']
            {
              "required":0,
              "validate_format":1,
              "default":"1"
            }
        [/cred_generic_field]
      </div>
      <span style="display: none;">[cred_field field="gift-quantity" force_type="field" class="form-control" output="bootstrap" value="[types field='gift-quantity' output='raw'][/types]"]</span>
      <span style="display: none;">[cred_field field="quantity-claimed" force_type="field" class="form-control" output="bootstrap" value="[types field='quantity-claimed' output='raw'][/types]"]</span>
	</div>
	<br />
	<p class="centre"><strong>Warning:</strong> Please be accurate as incorrect purchasing information can result in the happy couple or other people missing out!</p>
	</div>
	<div class="modal-footer">
	[cred_field field='form_submit' output='bootstrap' value='Submit' class='btn right']
[/credform]

What I'd like to do is hook my messages into the [cred_field field='form_messages'] field so that they appear naturally but I'm still working on that so if you see this before I post a solution (assuming I find one) I'd appreciate any pointers on that front as well.

#1275311

I think I've cracked this.

I've had to add a few bits and pieces into the code to tidy up the user interactions and make it actually work in a tidy manner, but for some reason I have encountered another issue that may or may not be related to this which is detailed in this support thread:

https://toolset.com/forums/topic/cred_before_save_data-cred_form_validate-not-firing/

Regardless, here is my finished, though largely uncommented JS that achieves the validation I needed along with simulating (I could find no way of hooking into existing functions) the error messages that Toolset use.

$(document).ready
  jQuery( function($) {
    $("input[name='amount-purchased']").live('change', check);
  });

  //setup before functions
  var typingTimer;                //timer identifier
  var doneTypingInterval = 5000;  //time in ms (5 seconds)

  //on keyup, start the countdown
  $("input[name='amount-purchased']").keyup(function(){
    clearTimeout(typingTimer);
    if ($("input[name='amount-purchased']").val()) {
      typingTimer = setTimeout(check, doneTypingInterval);
    }
  });

  function check($) {
  console.log("Jumped to function");
    var purchased = jQuery("input[name=amount-purchased]").val();
    var requested = jQuery("input[name=wpcf-gift-quantity]").val();
    var claimed = jQuery("input[name=wpcf-quantity-claimed]").val();
    var remaining = requested - claimed;
    
    if( purchased < '' ) {
      error_message( "Please enter a number" );
    } else if( purchased < 0 ) {
      error_message( "Please enter a positive number" );
    } else if ( purchased != Math.floor( purchased ) ) {
      error_message( "Please only enter whole numbers" );
    } else if ( purchased > remaining ) {
      error_message( "Please don't buy more than " + remaining );
    } else if ( purchased >= 0 && purchased <= remaining ) {
      submit_enable();      
    }

    function error_message( error ) {
      jQuery('#amount_error').removeAttr("style");
      document.getElementById("amount_error").innerHTML = error;
	  submit_disable();
    }
   
    function submit_disable() {
      jQuery( 'input[name="form_submit_2"]' ).attr( "disabled", "true" );
    }
    
    function submit_enable() {
      jQuery( 'input[name="form_submit_2"]' ).removeAttr( "disabled", "true" );
      jQuery('#amount_error').attr('style','display: none');
    }    
  }

Once the other thread is resolved and confirmed to be unrelated to this code I will close the support thread, I just don't want to do so prematurely and find there is important information or a huge issue with any of this that might mislead future readers should I not make it known.

Love to hear any feedback or thoughts though Shane.

#1275805

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Screenshot 2019-06-24 at 9.09.31 AM.png

Hi Dave,

Happy to see that you're able to get this running now.

Also for your next ticket, I suspect that something blocking the hook.

Is the hook placed in the functions.php file or the Toolset custom code section. If so then the code may not be activated to run.

If you're able to send a screenshot of where the code is then I might be able to see the issue.

Also the CRED form validation messages are populated using php, however there is a form messages div on the page.

Perhaps you can point your validation messages to this here.

Thanks,
Shane

#1275817

The function hooks are called from a functions.php file and were previously working but for the life of me I cannot figure out what is stopping them. I've sent Luo a database dump in the other thread but if you're curious then I'll put the php in here as well, as I really appreciate any help here as it's driving me mad.

/**  Create function to update the amount of the gift is purchased **/
function update_purchased_amount($form_data)
{
	
	//Assign current gift post id to variable
	$id = get_the_ID();

	//Check if there is an purchase amount entered and that it is not zero()
	if ( isset( $_POST['amount-purchased'] ) != 0 )	{
		
		//Load the existing amount of gifts claimed
		$bought = get_post_meta( $id, 'wpcf-quantity-claimed', true );
		
		//Load the amount of gifts purchased this time
		$new_bought = $_POST['amount-purchased'];
		
		//Add the amount of gifts purchased previously and now together
		$amount_bought = $bought + $new_bought;
		
		//Write the total amount of gifts purchased back to the database
		update_post_meta( $id, 'wpcf-quantity-claimed', $amount_bought );
		
		//Load the existing list of purchasers
		$purchasers = get_post_meta( $id, 'wpcf-purchaser', true );
		
		//Set the current user's id to the current purchasers
		$new_purchaser = get_current_user_id();
		
		//Force the amount bought into an integer and set it to the loop index number
		$index = (int) $new_bought;
		
		//If a gift has been purchased
		if ( $index > 0 ) {
			
			//Start a loop
			do {
				//Check if there are any existing purchasers
				if ($purchasers != 0 ) {
					//If there are then add a comma and the new purchaser to the list
					$purchasers = $purchasers . ", " . $new_purchaser;
				//If there are no existing purchasers
				} else if ( $purchasers == 0 ) {
					//Start the list with the current purchaser
					$purchasers = $new_purchaser;
				}
				//Reduce the index by one
				$index = $index - 1;
			//Repeat until the current purchaser has been logged the amount of times equivalent to the number of this gift they bought
			} while ( $index > 0 );
		}
		
		//Write the updated purchasers list back to the database
		update_post_meta( $id, 'wpcf-purchaser', $purchasers );
	}
}

//Add function call for when number of purchases form is submitted
add_action('cred_before_save_data_139', 'update_purchased_amount', 10, 1);
/**  Create function to redirect back to the correct point on the gift list after a gift is purchased **/
function gift_purchase_redirect() {
	
	/*echo 'cred_success_redirect action hook is triggered!';
        die();
	*/
	//Assign current gift post id to variable
	$id = get_the_ID();
	
	//$list = isset( $_POST['amount-purchased'] );
	
	$parent = toolset_get_related_post( $id, 'gift-list-gift', 'parent' );
	
	$url = get_page_link( 54 ) . "?fw-gift-list=" . $parent . "#gifts_anchor";
	
	return $url;

}

//Add function call to redirect when number of purchases form is submitted
add_action('cred_success_redirect_139', 'gift_purchase_redirect', 10, 1);

For what it's worth, I think you're right and something is blocking them as even removing my code then running just a die() function is not working.

Other hooks are working still but why on earth these two are having problems I can't figure out and none of the debugging options are giving me any answers sadly.

#1276117

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Dave,

I see no reason why this shouldn't work since the hook is setup correctly.

Unless the form ID's that the hook is meant to target has changed.

Maybe you can check this as well .

Thanks,
Shane

#1276133
Still 139.png

Sadly I already checked that one bud, and it's definitely still 139. I am absolutely stumped as to what is causing this and I'm still no closer to figuring it out so I'm hoping that Luo has some luck with the database dump.

Obviously if you have any other ideas please do let me know.

#1276619

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Dave,

I saw that Luo was able to have some luck on this.

Perhaps we can close here and you can continue with him in the ticket? It seems to be some conflict as suspected.

Thanks,
Shane