jQuery classname validation not working for dynamically generated text fields - php

I am facing a problem with jQuery Validation to validate the ajax (dynamically) generated text fields...
Here is the snippet of the HTML code
<form name="booking" id="booking" method="post" action="">
<ul>
<li>
<span>Mobile Number</span>
</li>
<li>
<input type="tel" name="mobile" id="mobile" class='form_mobile'/>
</li>
<li>
<span>Number of male tickets</span>
</li>
<li>
<select name="male_qunatity" id="male_qunatity" >
</select>
</li>
</ul>
</form>
Jquery validation script is here
$(document).ready(function(){
Here is the ajax call starts
$('#male_qunatity').change(function() {
var male_tickets = $(this).val();
var mobile = $('#mobile').val();
var path = '<?php echo site_url() ?>';
ajaxurl = path + '/wp-admin/admin-ajax.php';
var data = {
action: 'get_quantity',
qty: male_tickets,
mobile: mobile
};
$.post(ajaxurl, data, function(response) {
$('#m_attendees').html(response);
});
}); //END dropdown change event
$("#booking").validate({
});
$('.form_mobile').each(function() {
$(this).rules('add', {
required:true,
number:true,
messages: {
required:"Please enter a mobile number",
number:"Only numbers allowed"
}
});
});
});//validation ends
Here is the ajax code to text-boxes based on the count selected
$quantity= $_REQUEST['qty'];
$mobile= $_REQUEST['mobile'];
$pass = "<table>";
for($i =0; $i<$quantity; $i++ ){
$pass .= "<tr>
<td>
<input type='text' id='mobile-".$i."' class='form_mobile' name='mmobile[]'>
</td>
</tr>";
}
$pass .= "</table>";
echo $pass;
FYI: The form validation is working fine for the form fields, except the dynamically created fields..
How to solve this one?
Any suggestions would be greatly appreciated..

1) Since jQuery Validate depends on the name attribute, you'll need to alter your PHP to ensure that every name is unique. Note the index, $i, added to the name attribute...
"... <input type=text id='mobile-".$i."' name='mmobile[".$i."]' class='form_mobile'> ..."
(you're also missing quotes around text; should be type='text')
2) When creating fields dynamically, you would call .rules('add') AFTER the fields are dynamically created. In your case, here...
$.post(ajaxurl, data, function(response) {
$('#m_attendees').html(response); // <- create the new fields
$('.form_mobile').each(function() { // <- then dynamically add the rules
$(this).rules('add', {
required:true,
number:true,
messages: {
required:"Please enter a mobile number",
number:"Only numbers allowed"
}
});
});
});
3) .validate() is the initialization method for the plugin on your form. Just call it once when the DOM loads. (.validate() does not get called repeatedly when the form is validated, because validation is automatic once the plugin is properly initialized.)
$(document).ready(function() { // <- DOM is ready
$("#booking").validate({ // <- initialize plugin on your form
// your options // <- plugin options
});
});

Related

AJAX form submission, submitting another form even thought using $(this)

I have two forms on my page.
One is in the footer and is a contact page, but the other is my main form called "product-form". I am doing some validation in PHP:
foreach( $_POST as $field => $val ) {
if ($val == '') {
echo $field . "- no val <br>";
}
}
The issue is that I am seeing fields being validated that are in my footer form...
Here is my AJAX:
$('body').on('submit', '.product-form', function(e){
e.preventDefault();
var thisForm = $(this);
$.ajax({
url : '/wp-content/themes/theme/page-templates/template-parts/template-logic/send-form.php',
type : 'POST',
data : thisForm.serialize(),
before : $(".error-message").remove(),
success : function(data) {
}
});
});
How is this submitting the data from two forms?
Both forms have their tags properly closed off, with different class's too.
Have to use WordPress for this project, normally much more at home with Laravel validation so this is a bit of a throwback!
Requested form HTML:
Form I want:
<form method="post" class="product-form">
<li class="object field">
<label for="full name">Your full name <span>*</span></label>
<input class="req" autocomplete="off" type="text" name="full name" id="full name" placeholder="e.g. John Doe">
</li>
</form>
And the footer form:
<form class="footer-form small">
<li>
<button class="object button large" type="submit">Get in touch</button>
</li>
</form>
Please change it like this:
$( ".product-form" ).submit(function( e) {
e.preventDefault();
var thisForm = $(this);
$.ajax({
url : '/wp-content/themes/theme/page-templates/template-parts/template-logic/send-form.php',
type : 'POST',
data : thisForm.serialize(),
before : $(".error-message").remove(),
success : function(data) {
}
});
});

Form when submitted to display a result (Firstname) on the thank you page

Stuck on a thing with PHP, i know it is something simple but am not sure of the correct way of doing it, either by jquery or php.
I have a contact form which when it submits its form, i want the results of some of the fields to display on the results thank you paeg saying:
Thank you for entering YOURNAME. Blah blah blah
Is this acheivable with a simple line of php or does it need to called through jquery.
Thanks, only new to php so somethings are still bit confusing
<?php
define('is_freetrial-celebrity', 1);
include_once('includes/header.inc.php');
?>
<div role="main" id="main">
<article id="mainFreetrial" class="greyBlock twoColumnsLayout">
<header>
<h1>Get Started</h1>
</header>
<div>
<form method="get" action="/forms_validation/freetrial.php" class="trialForm ajaxForm">
<div class="column">
<p>
<label for="firstNameTrial">First name<sup class="red">*</sup></label><input type="text" id="firstNameTrial" name="firstNameTrial" value="" required/>
</p>
<p>
<label for="lastNameTrial">Last name<sup class="red">*</sup></label><input type="text" id="lastNameTrial" name="lastNameTrial" value="" required/>
</p>
<p>
<label for="ageTrial">Age</label><input type="text" id="ageTrial" name="ageTrial" value=""/>
</p>
<p>
<label for="celebrityTrial" style="display: block; width: auto; margin-bottom: 5px;">Name the celebrity you would most like to meet, and why?<sup class="red">*</sup></label>
<textarea id="celebrityTrial" name="celebrityWhyTrial" style="width: 430px; height: 3em;" required></textarea>
</p>
<p class="ajaxFormBeforeValid">
<input type="submit" value="Submit now" class="redButton"/><span class="ajaxFormWait"></span><span class="ajaxFormError error"></span>
</p>
<div class="ajaxFormValid">
<p>
Thank you! Your local consultant will contact you soon. 'Like' us while you wait for all the latest VIP offers and promotions!
</p>
</div>
<p>
<small>
<sup class="red">*</sup>These are mandatory fields.
</small>
</p>
</div>
</form>
</div>
</article>
</div>
<?php include_once('includes/footer.inc.php'); ?>
Heres the jquery part
/*************************
plugin to manage ajax forms
*************************/
(function( $ ){
var methods = {
init : function( options ) {
return this.each(function(){
var $this = $(this),
data = $this.data('ajaxForm'),
ajaxForm = $('<div />', {
text : $this.attr('title')
});
// If the plugin hasn't been initialized yet
if ( ! data ) {
$(this).data('ajaxForm', {
target : $this,
ajaxForm : ajaxForm
});
//get the spinner, the valid box and the error box
var mySpinner = $this.find('.ajaxFormWait');
var myValid = $this.find('.ajaxFormValid');
var myError = $this.find('.ajaxFormError');
var myBeforeValid = $this.find('.ajaxFormBeforeValid');
myError.hide();
mySpinner.hide();
//add an event to send the form via AJAX
$this.submit(function(){
// get all the inputs into an array.
var $inputs = $this.find(':input:not([type="submit"], [type="button"])');
// not sure if you wanted this, but I thought I'd add it.
// get an associative array of just the values.
var values = {};
$inputs.each(function() {
if (this.type == "radio" || this.type == "checkbox"){
if($(this).is(':checked')){
if(typeof(values[this.name]) === 'undefined'){
values[this.name] = $(this).val();
}else{
values[this.name] += ', '+($(this).val());
}
}
} else
values[this.name] = $(this).val();
});
function defineTheInvalidsFields(fieldsList){
for(var i in fieldsList){
if(fieldsList[i] == 'closestStudio'){
$this.find('[name="'+fieldsList[i]+'"]').parent().addClass('invalid');
}else{
$this.find('[name="'+fieldsList[i]+'"]').addClass('invalid');
}
}
}
//send an AJAX request
$.ajax({
url: $this.attr('action'),
dataType: 'json',
data: values,
beforeSend: function(){
mySpinner.show();
},
success: function(result){
mySpinner.hide();
$this.find('.invalid').removeClass('invalid');
//error management
if(typeof(result.valid) === 'undefined'){
if(result.multipleSend){ //if multiple send
myError.html('Your request is already sent.');
}else if(result.required){ //if fields are required
defineTheInvalidsFields(result.required);
myError.html('The fields in red are required.');
}else if(result.format){ //if the forma is incorrect
defineTheInvalidsFields(result.format);
myError.html('The fields in red have invalid content.');
}else if(result.loginInvalid){
myError.html(result.loginInvalid);
}else{
myError.html('An unknown error occured.');
}
myValid.slideUp(300);
myError.slideDown(300);
}else if(typeof(result.loginUrl) !== 'undefined'){
window.location.href = result.loginUrl;
}else{
if(result.valid || result.valid == 'true'){
if($('#inputFreetrialFitnessFirst').length){
myBeforeValid.slideUp(300);
myError.slideUp(300);
myValid.slideDown(300);
}else{
window.location = '/free-trial-thank-you/';
}
}else{
myError.html('There was an error sending your details. Please try again.');
myValid.slideUp(300);
myError.slideDown(300);
}
}
}
});
return false;
});
//special case for the heardAbout
$('#heardAbout').change(function(){
if($(this).find('option:selected').attr('value') == 'Other'){
$('#otherHeardAbout').slideDown(300);
}else{
$('#otherHeardAbout').slideUp(300);
}
});
}
});
},
destroy : function(){
return this.each(function(){
var $this = $(this),
data = $this.data('ajaxForm');
// Namespacing FTW
$(window).unbind('.ajaxForm');
data.ajaxForm.remove();
$this.removeData('ajaxForm');
})
}
};
$.fn.ajaxForm = function( method ) {
// Method calling logic
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.ajaxForm' );
}
};
})( jQuery );
The form gets sent to the other page, is there a way to target a specific div and add the custom message with the name.
if(result.valid || result.valid == 'true'){
if($('#inputFreetrialFitnessFirst').length){
myBeforeValid.slideUp(300);
myError.slideUp(300);
myValid.slideDown(300);
}else{
window.location = '/free-trial-thank-you/';
}
}else{
myError.html('There was an error sending your details. Please try again.');
myValid.slideUp(300);
myError.slideDown(300);
}
if You wand to fetch specific element div via ajax call You can do like this:
$.ajax({
url: 'page.html',
success: function(data) {
item=$(data).filter('#specific_element');
$(selector).html(item);
}
});
If You wand to redirect to other page using
window.location = '/free-trial-thank-you/';
and then show data on a different page You should pass needet parameters like
window.location = '/free-trial-thank-you/page.php?name1=Daniel&name2=Pablo;
and on different site show parameters using _GET or _POST for example:
echo $_GET['name1'] or echo $_POST['name1'] if You use PSOT method in Your Ajax request
One way that I can think of is using session to store the information.
At freetrial.php store the form information in session like this:
session_start();
$_SESSION['firtNameTrial'] = $_GET['firstNameTrial'];
On ajax success, redirect the page to the thank you page using javascript windows.location.replace:
// similar behavior as an HTTP redirect
window.location.replace("http://yourwebpageaddress.com/thankyou.php");
Get the session on the thank you page. If you don't know, you may look at this example: Click here for session example

AJAX Hash Submit Form

I'm pretty sure it has to do with my core.js file with the ajax hashing url. But I'm trying to submit a form, but it's not submitting like I want it to. This is the core.js file:
// call init
$(init);
function init() {
ajax_page_handler();
page_load($(window.location).attr("hash")); // goto first page if #! is available
}
function page_load($href) {
if($href != undefined && $href.substring(0, 2) == '#/') {
// replace body the #content with loaded html
$('#content').load($href.substring(2), function () {
$('#content').hide().fadeIn('slow');
});
}
}
function ajax_page_handler() {
$(window).bind('hashchange', function () {
$href = $(window.location).attr("hash");
page_load($href);
});
// this allow you to reload by clicking the same link
$('a[href^="#/"]').live('click', function() {
$curhref = $(window.location).attr("hash");
$href = $(this).attr('href');
if($curhref == $href) {
page_load($href);
}
});
}
The live viewing is over at www.krissales.com. The form is here: http://www.krissales.com/#/media/5.Testing-1
Hit the link "Post Comment", then you'll type info in, then hit comment, but it just refreshes, but doesn't submit it.
The steps I've taken to solve it was in the comment file, in the form action field, I inserted the tag name="#content" simply because that's the name of my div that I'm submitting to.
The original stuff is on http://blog.krissales.com/article/7.Testing-3-man ( where you can actually post a comment, and it'll work)
But apparently it's not working. Do you guys have a clue as to what it is that I'm doing wrong? thanks for your help in advance!
<script type="text/javascript">
tinyMCE.init({
mode : "textareas",
theme : "simple"
});
</script>
<form action="#/media/article.php" name="#content" method="POST">
Name:
<br />
<input type="text" name="name" class="userpass"/>
<br /><br />
Comment:
<br />
<textarea id="elm1" name="comment" rows="7" cols="30" style="width: 500px;">
</textarea>
<br />
<input type="submit" name="submit" value="Comment" class="button" />
<input type="reset" name="submit" value="Reset" class="button" />
</form>
I noticed that you are not setting the ajax type on the file 'comment.php'.
you need...
$.ajax({
type: 'POST',
url: 'comment_ajax.php',
data: { form_name: name, form_comment: comment },
success: function(data) {
$('#new_comment').prepend(data);
// close modal box
// do other shit
// kthnxbai
}
});
If type is not specified, it defaults to a GET request which will not post data. :)
Your current core.js handles changes in the URL hash, and it reroutes any links with a hash to load that relative path into #content. What's missing is code to redirect form submits to do the same thing (add this to ajax_page_handler):
$('form').live('submit', function(e) {
var $action = $(this).attr('action');
if($action.substring(0, 2) == '#/') {
// replace the #content with result of the form post
$.ajax({
url: $action.substring(2),
type: $(this).attr('method'),
data: $(this).serialize(),
success: function(data) {
$('#content').html(data);
$('#content').hide().fadeIn('slow');
}
});
// stop the real form submit from happening
e.preventDefault();
}
});
You should change the action attribute of your form like this :
<form action="script-handling-comment-data.php#/media/article.php" name="#content" method="POST">
For the moment, you're sending the comment data to http://www.krissales.com/ and i think the main page doesn't handle the comment posting.
You seem to be handling links properly, but form submission isn't a link, you probably want to handle submission using $(form).submit(function(){ ... })
In your case, if you gave your form the id form1
$('#form1').submit(function(){
var keyValues = $(this).serializeArray();
var map = {};
for(i in keyValues)
{
var value = keyValues.value;
var name = keyValues.name;
map[name] = value;
}
$.post($(this).attr('action'),map,function(){
alert("Submitted values: " + $(this).serialize());
});
return false;
})
See serializeArray, $.post and .submit for more information

jQuery clone table row in form does not submit cloned fields

Below is a simplified example that demonstrates the problem I am having. One hundred percent of code is posted below.
Three files work together: testa.php, testb.php, and testc.js. (FWIW, testa.php could function as the index.php, but this is just a demo)
OVERVIEW:
TESTA.PHP
When user clicks anchor tag, sends value to testb.php
Receives ajax response from testb.php into div #reportstable, within FORM structure
Form is submitted to itself, so it prints $_POST data -
TESTB.PHP
receives value from TESTA.PHP, via ajax
outputs table that corresponds to received values
(In this example, I removed how received value is used, but still retained this structure as it affects the jQuery in testc.js)
TESTC.JS
the jQuery that makes it (partially) work
PROBLEM 1: If user adds more than one "document" (i.e. row), only data for the last document appears in the POST data..
PROBLEM2: DocTitle and FileName IDs (dt1, fn1) are not POSTED as they appear in the DOM. In the DOM, their IDs are incremented properly (dt11, dt12, dt13, etc) but when POSTed only one comes through and it has not been incremented. (Use firebug to inspect table elements after adding a couple of documents.
PROBLEM3: First click doesn't "take" when clicking the "choose file" anchor when adding a new document. Any thoughts on this one?
TESTA.PHP
<?php
If (empty($_POST)===false) {
echo '<pre>';
print_r($_POST);
echo '</pre>';
die();
}
?>
<html><body>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="jquery-custom-file-input.js"></script>
<script type="text/javascript" src="testc.js"></script>
<br />
Project*:<br />
Click Me
<form action="" method="post">
<div id="reportstable">
</div>
</form>
</body></html>
TESTB.PHP
<?php
$project_id = $_POST['project_id'];
if ($project_id == 5) {
echo '
<table id="DocTable">
<tr>
<th width="150">Document Title</th>
<th width="150">File Name</th>
</tr>
<tr name="tr2" id="tr2" style="display:none;">
<td><input type="text" name="dt1" id="dt1"></td>
<td>
<input type="hidden" name="fn1" id="fn1">
<span id="sp1">choose file<span>
</td>
</tr>
</table>
<br />
add document<br />
<br />
<input type="submit" name="submit" id="submit_it" value="Submit">
';
}
TESTC.JS
$(function(){
var count = 1;
//*******************************************************************
$('#project_pick').click(function(e) {
$(this).hide();
$.ajax({
type: "POST",
url: "testb.php",
data: "project_id=5",
success:function(data){
$('#reportstable').html(data);
}
});
});
//*******************************************************************
$(document).on('click','#ah11',function() {
$(this).file().choose(function(e, input) {
$('#fn11').val(input.val());
$('#sp11').html(input.val());
$('#sp11').css('color','grey');
});
});
//*******************************************************************
$(document).on('click','#ah12',function() {
$(this).file().choose(function(e, input) {
$('#fn12').val(input.val());
$('#sp12').html(input.val());
$('#sp12').css('color','grey');
});
});
//*******************************************************************
$(document).on('click','#ah13',function() {
$(this).file().choose(function(e, input) {
$('#fn13').val(input.val());
$('#sp13').html(input.val());
$('#sp13').css('color','grey');
});
});
//*******************************************************************
$(document).on('click', '#add_row', function() {
$("table#DocTable tr:nth-child(2)")
.clone()
.show()
.find("a, input, span, tr").each(function() {
$(this)
.val('')
.attr('id', function(_, id) {
return id + count;
});
})
.end()
.appendTo("table");
count++;
if (count == 4) {
$('#add_row').prop('disabled', 'disabled');
}
}); //end fn add_row
//*******************************************************************
$(document).on('click', '#submit_it', function() {
alert('This will be submitted now');
});
//*******************************************************************
});
It seems in your javascript that you are changing the values of the id attribute only. However, when you post a form, the id attribute is irrelevant and not posted, you need the name attribute instead.
So where you are changing id's, you really should be changing names (and id's to if you really need them as they need to be unique).
However, a far easier solution would be to use arrays for names, like:
<input type="text" name="dt[]">
If you copy / clone elements with these names and post the form, you will get an array in your $_POST['dt'].

Jquery not considering new div that is added by Jquery + php + jquery

I have a php page where I add and delete items from database using Jquery + PHP + AJAX.
Now I am able to delete and add when that page loads for the first time.
Now if I first add an element; which in turn adds record to the DB and then updates the div that contains all the listing of divs.
Example:
<div id="all_items">
<div id= "item_1">
<a id="delete_link">...</a>
</div>
<div id= "item_2">
<a id="delete_link">...</a>
</div>
.... Upto Item n
</div>
Now I replace the div with id all_items.
Now I have jQuery at the bottom of the page which calls ajax on a tag of delete_link.
Situtation is:
When page is loaded I can delete any item from the list.
But if I page load i add new item first. (which will update all_items div) after that if I try to click on delete link. Jquery on click selector event is not fired and which in turn doesn't do delete ajax operation.
I couldn't figure out why this is happening.
Looking for some help here.
EDITED:
Sorry for not writing code earliar.
Following is the jQuery I am talking about.
<script type="text/javascript" >
var jQ = jQuery.noConflict();
jQ(function() {
jQ("#submit_store").click(function() {
var store_name = jQ("#store_name").val();
var dataString = 'store_name='+ store_name;
dataString += '&mode=insert';
if(store_name =='')
{
alert("Please Enter store Name");
}
else {
jQ.ajax({
type: "POST",
url: "<?php echo $mycom_url; ?>/store_insert.php",
data: dataString,
cache: false,
success: function(html){
jQ("#dvstoreslists").html(html);
document.getElementById('store_name').value='';
document.getElementById('store_name').focus();
}
});
}
return false;
});
jQ(".store_delete").click(function() {
var store_id = jQ(this).attr('id');
var id = store_id.split("_");
var dataString = 'store_id='+ id[2];
dataString += '&mode=delete';
var to_delete = "#store_list_" + id[2]
jQ.ajax({
type: "POST",
url: "<?php echo $mycom_url; ?>/store_insert.php",
data: dataString,
cache: false,
success: function(html){
jQ(to_delete).hide("slow");
}
});
return false;
});
});
</script>
So If on page load, I delete then delete on click jquery event is fired. But after adding new store and replacing div of stores with new div. then jQuery on click event is not fired.
My HTML is as below.
<div class="sbBox stores">
<form id="add_storefrm" name="add_storefrm" method="post" action="" >
<div class="dvAddStore">
<div class="dvName" id="store_list">
<input type="text" id="store_name" name="store_name">
<input type="hidden" value="addstore" id="mode" name="mode">
</div>
<div class="btnAddStore">
<input type="submit" name="submit_store" value="Add Store" id="submit_store">
</div>
</div>
<div id="dvstoreslists">
<?php
$query = "SELECT * FROM #__shoppingstore order by store_id desc;";
$db->setQuery($query);
$rows = $db->loadObjectList();
foreach($rows as $row)
{
echo "<div class=dvlist id=store_list_".$row->store_id ."><div class=dvStoreListLeft>";
echo "<div class='slname'><h3>" . $row->store_name . "</h3></div>";
?>
<div class="slDelBtn">
<p id = "p_store_<?php echo $row->store_id ; ?>">
<a id="store_delete_<?php echo $row->store_id ; ?>" class="store_delete" alt="Delete" onclick="DeleteStore(<?php echo $row->store_id ; ?>);" >
</a>
</p>
</div>
</div>
</div>
<?php } ?>
</div>
</form>
</div>
Sorry folks for not posting the code earliar.
the ID should always be unique so use class instead
in your case : <a id="delete_link">...</a> to <a class="delete_link">...</a>
When you replace the contents of #all_items any event handlers that were bound to any descendants will no longer exist. You can use event delegation, using the on method, to solve this:
$("#all_items").on("click", ".delete_link", function() {
//Do stuff
});
Notice that I'm using a class selector (.delete_link) instead of an ID selector for the links. It's invalid to have duplicate IDs in the same document.
Also note that the above will only work if you are using jQuery 1.7 or above. For older versions, use delegate instead:
$("#all_items").on(".delete_link", "click", function() {
//Do stuff
});
This works because DOM events bubble up the tree from their target. So a click on a link which is a descendant of #all_items will bubble up through all of its ancestors and can be captured when it reached #all_items.
use live() instead of .bind()
It seems you are trying to delete dynamically added delete_link so i think you should use
$('id or class').on(click,function(){});

Categories