This is very consistent, but firebug is showing that my saveForm function is not being defined form my 'button.save' event handler, but it works for my 'button.deleteForm' event handler:
function saveForm(form)
{
var $form = form;
var url = $form.attr('action');
$.ajax({
type: "POST",
enctype: 'mutipart/form-data',
url: url,
data: $form.serialize(), // serializes the form's elements.
success: function(data)
{
// data is the server response.
// change this function to tell the
// user whether their submission
// is correct or what fields have
// bad data.
var response = JSON.parse(data);
return true;
}
});
return false; // avoid to execute the actual submit of the form.
}
// Do not use event handlers like .click(). This is the
// only viable solution for handling events on dynamically
// generated HTML elements. This handles the saving of data
// to the server.
$(document).on('click', 'button.save', function(e){
var $form = $(this).closest('form');
saveForm(form);
});
// This event handler is responsible for deleting data.
// For Joey's job: Please make sure that this calls save
// after the user hits delete. This will save the data in
// the database.
$(document).on('click', 'button.deleteForm', function(e){
// Get the form to update before deleting our embedded form
var $form = $(this).closest('form');
var str = $(this).attr('id');
// Get the table id in review to delete
var deleteForm = str + '_review';
$('table#' + deleteForm).remove();
// Get the collection form id to delete
var idArray = str.split('_');
idArray.pop();
divId = '#' + idArray.join('_');
$(divId).remove();
saveForm($form);
});
you missed $ in saveform
$(document).on('click', 'button.save', function(e){
var $form = $(this).closest('form');
saveForm($form);
//------^----here
});
Related
Sorry I am a beginner with jQuery and Javascript. I want to be able to get the results into my modal from any form on the page that has class ajax. My code is below but not working correctly. Currently it opens the post result in a new page and not in the modal. Can anyone shed any light on my code?
Many thanks
$(document).ready(function() {
$('.ajax').click(function() {
var that = $(this),
url = that.attr('action'),
type = that.attr('method'),
data = {};
that.find('name').each(function(index, value) {
var that = $(this),
name = that.attr('name'),
value = that.val();
data[name] = value;
});
console.log(value);
// AJAX request
$.ajax({
url: url,
type: type,
data: data,
success: function(response){
// Add response in Modal body
$('.modal-body').html(response);
// Display Modal
$('#aaModal').modal('show');
}
});
});
});
This probably happens because your browser submits the form by default. It doesnt know youre doing AJAX stuff. To prevent this, use preventDefault().
In addition to that, jQuery has a built in function for serializing (1 and 2) form data.
$(document).ready(function() {
$('form.ajax').click(function(event) {
event.preventDefault(); // prevents opening the form action url
var $form = $(this),
url = $form.attr('action'),
type = $form.attr('method'),
data = $form.serialize();
// console.log(value); // value doesnt exist outside of your loop btw
// AJAX request
$.ajax({
url: url,
type: type,
data: data,
success: function(response){
// Add response in Modal body
$('.modal-body').html(response);
// Display Modal
$('#aaModal').modal('show');
}
});
});
});
Also, its not quite clear if you bind the click event handler to a form or a button, I guess the first one. You should change the handler to the following:
$(document).ready(function() {
$('form.ajax').on('submit', function(event) {
I'm trying to get all elements from Form using JavaScript. I have tried the below method but I am still unable to extract all elements.
Are there any suggestions anyone can provide to extract all Form elements information?
$(document).ready(function(){
// References:
var $form = $('#rForm');
var $subm = $('#submitForm');
var $impt = $form.find(':option, :input').not(':button, :submit, :reset, :hidden');
// Submit function:
$form.submit(function(){
$.post($(this).attr('action'), $(this).serialize(), function(response){
// On success, clear all inputs;
$impt.val('').attr('value','').removeAttr('checked').removeAttr('selected');
},'json');
return false;
});
});
I would like to validate a form with an AJAX request to the server and then swap the form html in the web browser with the form html from the server because this would be an easy implementation in theory. It is proving a nightmare though because the change event is triggered without the user interacting further after the first interaction which triggered the first change event. Consequently an infinite loop of AJAX requests to the server is happening.
The html form sits inside a div which has classes 'container mb-4'. This is the JS code -
var _cont = $('.container.mb-4')
var _form = $('.custom-form')
function ajax_validation(form) {
form.on('change', 'input, select, textarea', function() {
form_data = form.serialize()
$.ajax({
url: "/form/6/",
type: "POST",
data: form_data,
success: function(data) {
if(!(data['success'])) {
_cont.empty()
_cont.append(data['form_html'])
form = _cont.find('form')
ajax_validation(form)
}
},
error: function () {
form.find('.error-message').show()
}
});
})
}
ajax_validation(_form)
The change event I am assuming is triggered because the server returns a form input field with a different csrf token as the value to the previous input field - all other fields are the same. So an obvious solution would be to keep the same csrf token. But I want to understand why the JS code isn't working. I thought destroying the form would destroy the change event bound to it. So am at a loss to explain this infinite loop. How do I change this so I can just swap the form and not trigger another change event until the user really does change something?
It's not a good thing to use events in function no need to do that
Also your event here for input , select , textarea for serialize you need to select the closest() form
Try the next code
var _cont = $('.container.mb-4');
var _form = $('.custom-form');
_cont.on('change', 'form input,form select,form textarea', function() {
var ThisForm = $(this).closest('form');
var form_data = ThisForm.serialize();
$.ajax({
url: "/form/6/",
type: "POST",
data: form_data,
success: function(data) {
if(!(data['success'])) {
_cont.html(data['form_html']);
}
},
error: function () {
ThisForm.find('.error-message').show()
}
});
});
And logically if(!(data['success'])) { should be if(data['success']) {
First let's understand the issue that you have. You have a function called ajax_validation that is defining a change event on the form's elements which, on response will call ajax_validation. So, if any change happens on your elements, then a new request is sent to the server. So, if any value is changed, like a token, the request will be sent again. You could use a semaphore, like this:
var semaphore = true;
function ajax_validation(form) {
form.on('change', 'input, select, textarea', function() {
if (!semaphore) return;
semaphore = false;
form_data = form.serialize()
$.ajax({
url: "/form/6/",
type: "POST",
data: form_data,
success: function(data) {
if(!(data['success'])) {
_cont.empty()
_cont.append(data['form_html'])
form = _cont.find('form')
ajax_validation(form)
}
semaphore = true;
},
error: function () {
form.find('.error-message').show()
}
});
})
}
Something like this should solve your issue for the time being, but you should consider refactoring your code, because what you experience is well-known and is called callback hell.
Turns out the password field was coming back blank from the server - this django must do out of the box if the PasswordInput widget is used. So the form is replaced with a new form which lacks the password input from the before. The browser was then applying the autofill password value to the form which was triggering the change event.
This is my code now. It checks that the form_data about to be sent for validation really is different to before minus the csrf token which will be different.
It is based on Mohamed's answer -
var _cont = $('.container.mb-4');
var _form = $('.custom-form');
var prev_data = undefined
_cont.on('change', 'form input,form select,form textarea', function() {
var ThisForm = $(this).closest('form');
var form_data_wo_csrf = ThisForm.find("input, textarea, select").not("input[type='hidden']").serialize()
if(form_data_wo_csrf == prev_data) {
return
}
var form_data = ThisForm.serialize()
$.ajax({
url: "/form/6/",
type: "POST",
data: form_data,
success: function(data) {
if(!(data['success'])) {
_cont.html(data['form_html']);
prev_data = form_data_wo_csrf
}
},
error: function () {
ThisForm.find('.error-message').show()
}
});
});
I have forms being created in a foreach loop with php.
Each form has a lpformnum that increases
<form lpformnum="1"><button class="update" /></form>
<form lpformnum="2"><button class="update" /></form>
<form lpformnum="3"><button class="update" /></form>
etc.
I am using jquery/ajax to prevent the default action of the forms so I can submit the forms via ajax.
<script>
$(document).ready(function(){
$('.alert').on('click', 'button[class=update]', function(e) {
e.preventDefault();
e.stopPropagation();
var checkValues = $("#update").val();
var checkCred = $("#ucredits").val();
var checkPost = $("textarea").text();
var checkType = $("i").text();
$.ajax({
type: "POST",
url: "update_social_cred.php",
data: { id: checkValues, credits: checkCred, text: checkPost, type: checkType },
success:function(result) {
alert (checkCred);
}
});
});
});
</script>
The problem is, every button submits the first form drawn on the page. How would I do this so each button is set to each form keeping in mind there are an unknown number of forms being drawn?
I suppose you should clarify what data you want to submit with find() method.
$('.alert').on('click', 'button[class=update]', function(e) {
e.preventDefault();
e.stopPropagation();
// find parent form of a button
var form = $(this).closest( "form" );
// I suppose these are unique fields.
var checkValues = $("#update").val();
var checkCred = $("#ucredits").val();
var checkPost = $("textarea").text();
// if they are not you should use classes instead:
// something like:
// var checkCred = form.find(".ucredits").val();
// find values in a `form` with `find` method
var checkType = form.find("i").text();
// pass your data to ajax.
How can refactor this below jQuery code.
All the functions does the same job but on different key-presses on the table search box. Which is filtering the table data.
I want re factor this code and write it in single function. Please help me.
jQuery(function($) {
// when the #name field changes
$("body").on("keypup", "#name", function() {
var form = $("#users_form"); // grab the form wrapping the name bar.
var url = form.attr("action");
var formData = form.serialize();
$.get(url, formData, function(data) {
$("#reseller_admin_list").html(data); // replace the "results" div with the result of action taken
});
$("body").on("keypup", "#login", function() {
var form = $("#users_form"); // grab the form wrapping the name bar.
var url = form.attr("action");
var formData = form.serialize();
$.get(url, formData, function(data) {
$("#reseller_admin_list").html(data); // replace the "results" div with the result of action taken
});
$("body").on("keypup", "#account_manager", function() {
var form = $("#users_form"); // grab the form wrapping the name bar.
var url = form.attr("action");
var formData = form.serialize();
$.get(url, formData, function(data) {
$("#reseller_admin_list").html(data); // replace the "results" div with the result of action taken
});
$("body").on("keypup", "#email", function() {
var form = $("#users_form"); // grab the form wrapping the name bar.
var url = form.attr("action");
var formData = form.serialize();
$.get(url, formData, function(data) {
$("#reseller_admin_list").html(data); // replace the "results" div with the result of action taken
});
});
});
function update() {
var form = $("#users_form"); // grab the form wrapping the name bar.
var url = form.attr("action");
var formData = form.serialize();
$.get(url, formData, function(data) {
$("#reseller_admin_list").html(data); // replace the "results" div with the result of action taken
});
}
$("body").on("keyup", "#account_manager, #login, #email", update);
The explanation:
1.) We extract the duplicate code in a single function called update. We follow the DRY principle here
2.) JQuery allows us to use multiple selectors, so we can bind the update function to all elements at once:
$("body").on("keyup", "#account_manager, #login, #email", update);
instead of calling:
$("body").on("keyup", "#account_manager", update);
$("body").on("keyup", "#login", update);
$("body").on("keyup", "#email", update);
how about just having one code block:
$("body").on("keypup", "#name, #login, #account_manager, #email", function() {
var form = $("#users_form");
var url = form.attr("action");
var formData = form.serialize();
$.get(url, formData, function(data) {
$("#reseller_admin_list").html(data);
});
});
Much better though, would be to give you elements a class, and bind to the class rather then each id, i.e.
$("body").on("keypup", ".someClass", function() { //etc
write a new function.
$("body").on("keypup", "#login", function() {
functionName();
});
and in function
function functionName(){
var form = $("#users_form"); // grab the form wrapping the name bar.
var url = form.attr("action");
var formData = form.serialize();
$.get(url, formData, function(data) {
$("#reseller_admin_list").html(data); // replace the "results" div with the result of action taken
});`
}