I have tabs with next and previous buttons on the bottom, when I first load the page ajaxloads data in to tab one, when I click next that form will submit fine, but if I press previous after pressing next it'll pull another ajax to populate the first dive the same way I was doing it on load, but when I click next to submit the form, the ajax request doubles and submits twice, then 4 times 8 etc, how can I stop this from happeing.... my jquery on one of my pages which is the same on all:
$(document).on("click",".previous", function()
{
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/personal_information',
type: 'GET',
success: function(data){
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab1').html(data);
$('#tab1').addClass('active');
$('.tab_1').addClass('active');
}
});
});
$(document).on("click",".next", function()
{
$('#update_contact_information').on("submit", function()
{
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
dataType: 'json',
data: $(this).serialize(),
success: function(data){
if(!data.success){
$.notify(data.error,{
className:'error',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab2').html('');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}else{
$.notify(data.success,{
className:'success',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}
}
});
return false;
});
$('#update_contact_information').trigger('submit');
});
my tabs:
<div class="panel-body">
<div id="rootwizard">
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<ul class="nav nav-pills">
<li class="active tab_1"><a href="#tab1" data-toggle="tab"><?php echo System::translate("Personal information"); ?></a></li>
<li class="tab_2"><a href="#tab2" data-toggle="tab"><?php echo System::translate("Contact information"); ?></a></li>
<li class="tab_3"><a href="#tab3" data-toggle="tab"><?php echo System::translate("Employment history"); ?></a></li>
<li class="tab_4"><a href="#tab4" data-toggle="tab"><?php echo System::translate("Qualification history"); ?></a></li>
<li class="tab_5"><a href="#tab5" data-toggle="tab"><?php echo System::translate("Avatar"); ?></a></li>
</ul>
</div>
</div>
</div>
<div class="tab-content">
<div class="tab-pane active" id="tab1">
</div>
<div class="tab-pane" id="tab2">
</div>
<div class="tab-pane" id="tab3">
</div>
<div class="tab-pane" id="tab4">
</div>
<div class="tab-pane" id="tab5">
</div>
<ul class="pager wizard">
<li class="previous"><a href="javascript:;"><?php echo System::translate("Previous"); ?></a></li>
<li class="next"><a href="javascript:;"><?php echo System::translate("Next"); ?></a></li>
</ul>
</div>
</div>
and the initial call:
<script>
$(function(){
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/personal_information',
type: 'GET',
success: function(data){
$('#tab1').html(data);
}
});
});
</script>
I have tabs with next and previous buttons on the bottom, when I first load the page ajaxloads data in to tab one, when I click next that form will submit fine, but if I press previous after pressing next it'll pull another ajax to populate the first dive the same way I was doing it on load, but when I click next to submit the form, the ajax request doubles and submits twice, then 4 times 8 etc, how can I stop this from happeing.... my jquery on one of my pages which is the same on all:
$(document).on("click",".previous", function()
{
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/personal_information',
type: 'GET',
success: function(data){
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab1').html(data);
$('#tab1').addClass('active');
$('.tab_1').addClass('active');
}
});
});
$(document).on("click",".next", function()
{
$('#update_contact_information').on("submit", function()
{
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
dataType: 'json',
data: $(this).serialize(),
success: function(data){
if(!data.success){
$.notify(data.error,{
className:'error',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab2').html('');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}else{
$.notify(data.success,{
className:'success',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}
}
});
return false;
});
$('#update_contact_information').trigger('submit');
});
my tabs:
<div class="panel-body">
<div id="rootwizard">
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<ul class="nav nav-pills">
<li class="active tab_1"><a href="#tab1" data-toggle="tab"><?php echo System::translate("Personal information"); ?></a></li>
<li class="tab_2"><a href="#tab2" data-toggle="tab"><?php echo System::translate("Contact information"); ?></a></li>
<li class="tab_3"><a href="#tab3" data-toggle="tab"><?php echo System::translate("Employment history"); ?></a></li>
<li class="tab_4"><a href="#tab4" data-toggle="tab"><?php echo System::translate("Qualification history"); ?></a></li>
<li class="tab_5"><a href="#tab5" data-toggle="tab"><?php echo System::translate("Avatar"); ?></a></li>
</ul>
</div>
</div>
</div>
<div class="tab-content">
<div class="tab-pane active" id="tab1">
</div>
<div class="tab-pane" id="tab2">
</div>
<div class="tab-pane" id="tab3">
</div>
<div class="tab-pane" id="tab4">
</div>
<div class="tab-pane" id="tab5">
</div>
<ul class="pager wizard">
<li class="previous"><a href="javascript:;"><?php echo System::translate("Previous"); ?></a></li>
<li class="next"><a href="javascript:;"><?php echo System::translate("Next"); ?></a></li>
</ul>
</div>
</div>
and the initial call:
<script>
$(function(){
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/personal_information',
type: 'GET',
success: function(data){
$('#tab1').html(data);
}
});
});
</script>
Share
Improve this question
asked Mar 1, 2016 at 17:51
user4655002user4655002
4
- 4 Remove the binding of the submit handler from the click handler. – Musa Commented Mar 1, 2016 at 17:53
- But I'd like to submit the form on the click of the next button.. – user4655002 Commented Mar 1, 2016 at 18:00
- what does the rest of your HTML look like? where is "#update_contact_information"? – trenthaynes Commented Mar 4, 2016 at 4:07
- Move submit binding outside $(document).on("click",".next", function(){ ... }); – itzmukeshy7 Commented Mar 10, 2016 at 13:08
8 Answers
Reset to default 8You are binding a new submit event to the form every time you click the button, that is why it doubles up. Remove the binding from inside the clickk handler
$(document).on("click",".next", function()
{
$('#update_contact_information').trigger('submit');
});
$(document).on("submit", '#update_contact_information', function()
{
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
dataType: 'json',
data: $(this).serialize(),
success: function(data){
if(!data.success){
$.notify(data.error,{
className:'error',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab2').html('');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}else{
$.notify(data.success,{
className:'success',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}
}
});
return false;
});
In two previous answers people are (correctly) suggesting you to restructure your code in order to avoid registering event handler inside another event handler. Yet, as you don't accept those answers, I suppose this doesn't pletely answer the question.
What you want to do is to do is to simply submit the form's content when you click the "next" button. At the same time, this button is not part of the form, therefore just clicking it will not trigger the "submit" event. So you are triggering the event manually.
Now what is strange in your description is that your ajax requests are doubling on every click. Normally with each click you'd have just one more request added. See my fiddle here, which is the simplified version of your code.
var form = $('form');
$(document).on('click', '.next', function(){
form.on('submit', function() {//with every click one more handler is registered. Click the "click" link several times to see
alert('submit fired');
return false;
});
form.trigger('submit')
})
Thus, the question arises: where do you register your handler with $(document).on("click",".next", function()
? You need to make sure that this handler is only registered once. For this you can put alert('registering handler')
just before this line in your code to check.
The correct sequence of registering event handlers is showing in this modified fiddle. The code is:
var form = $('form');
$(document).on('click', '.next', function(){
form.trigger('submit')
})
form.on('submit', function() {//with every click one more handler is registered. Click the "click" link several times to see
alert('submit fired');
return false;
});
So to proceed can you try what I suggested and let me know the result?
P.S. I'm not sure why you need to trigger form submission at all. For your ajax request you are serializing the form and cancelling initial submission (you return false
;). Thus I'd remend to avoid using "submit" events at all, and just to do all the work in the "click" handler.
UPDATE (after more information was added in the ment below)
So the second part of the problem is following. With every "next" click you are attaching new event listeners and you are replacing the html of your tabs like this $('#tab2').html(data);
, and data
contains not only markup, but also js code that is being executed when you insert it (btw, I didn't know that it works like this, it's nice). I think that what you are expecting is that once markup (html) is removed, corresponding event listeners will be removed as well. But in fact it's not the case. Why? Because you are delegating your event listening to document
with the code starting with:
$(document).on("click",".next", function()
Here $(document)
is what you are attaching your listener to. Instead of going into details I strongly suggest you to check out this original jquery explanation of event delegation.
So how do you fix it? There are several different ways. Possibly the simplest one (minimal amount of code editing) is to remove your event listeners before you do .html(data)
. Another way, also simple, is to write
$('.next').on("click", function(),
as you've done in qualification_history.php. This way you are attaching events to the element itself, and not to the document. The only thing is that you want to be sure that there is a corresponding DOM element before this code gets executed (so you might put your code after the markup).
Without knowing the full html of the page involved, there is some guessing in this. The code in the OP is not structured correctly and has other logic errors. The problem in a nutshell is that you have defined an event handler to add an event handler.
By putting $('#update_contact_information').on("submit", function(){...})
inside the handler definition for $(document).on("click",".next", function(){...})
, you are saying:
Every time I click on the a button with a class of next
, I want to create a new event handler for my element with the id of update_contact_information
. So the first time you click next
, you define and then trigger submit
. The second time you click next
, there is already an existing handler for the submit, plus you add another.
Because you haven't provided the rest of the HTML and JavaScript involved, it is not clear where your code exists. There are likely other issues as well.
I would restructure the JavaScript, putting all of the event handlers inside the jQuery on ready function for the page. This allows you to define your event handlers once, and still make your initial call to load the page.
Something like this:
$(function() {
$(document).on("click", ".previous", function() {
$.ajax({
url: '<?php echo Config::get('
URL '); ?>wizzard/personal_information',
type: 'GET',
success: function(data) {
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab1').html(data);
$('#tab1').addClass('active');
$('.tab_1').addClass('active');
}
});
});
$('#update_contact_information').on("submit", function() {
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
dataType: 'json',
data: $(this).serialize(),
success: function(data) {
if (!data.success) {
$.notify(data.error, {
className: 'error',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('
URL '); ?>wizzard/employment_history',
type: 'GET',
success: function(data) {
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab2').html('');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
} else {
$.notify(data.success, {
className: 'success',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('
URL '); ?>wizzard/employment_history',
type: 'GET',
success: function(data) {
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}
}
});
return false;
});
$(document).on("click", ".next", function() {
$('#update_contact_information').trigger('submit');
});
$.ajax({
url: '<?php echo Config::get('
URL '); ?>wizzard/personal_information',
type: 'GET',
success: function(data) {
$('#tab1').html(data);
}
});
});
Depending on the rest of your HTML and JavaScript code for your page, this may or may not work as is for you. I'm providing a fiddle that demonstrates something similar in action. It is not an exact duplicate of the original post, because the logic that example does not work. It should be a sufficient starting point for:
- Solving your existing problem of multiple event bindings
- Giving you a better place to start for fixing the logic problems in your original examples
Here is the fiddle
This should help with the order and logic of your events
//bind only when the doc has rendered...
$(document).ready(function() {
//bind click to and element with class previous
$(".previous").on("click", function()
{
//... previous code
alert("test me ;-)");
}
//bind click to and element with class next
$(".next").on("click", function()
{
//... next code.
alert("test me ;-)");
}
}
I suppose that the element witch id is #update_contact_information
is not exists at the beginning. You want to bind an event on .next
clicked. So, I suggest you use $.delegate
to bind event before element shows.
more information see .delegate()
.
e.g.
$(document).delegate('#update_contact_information','submit', function(){
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
dataType: 'json',
data: $(this).serialize(),
success: function(data){
if(!data.success){
$.notify(data.error,{
className:'error',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab2').html('');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}else{
$.notify(data.success,{
className:'success',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}
}
});
return false;
});
As per my ment
$(document).on("click",".previous", function(){
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/personal_information',
type: 'GET',
success: function(data){
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab1').html(data);
$('#tab1').addClass('active');
$('.tab_1').addClass('active');
}
});
});
$(document).on("click",".next", function(){
/* Submit binding code from here moved just after this block. */
$('#update_contact_information').trigger('submit');
});
/* submit binding code from above block */
$('#update_contact_information').on("submit", function(){
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
dataType: 'json',
data: $(this).serialize(),
success: function(data){
if(!data.success){
$.notify(data.error,{
className:'error',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab2').html('');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}else{
$.notify(data.success,{
className:'success',
clickToHide: true,
autoHide: true,
globalPosition: 'bottom right'
});
$.ajax({
url: '<?php echo Config::get('URL'); ?>wizzard/employment_history',
type: 'GET',
success: function(data){
$('#tab2').html('');
$('#tab2').removeClass('active');
$('.tab_2').removeClass('active');
$('#tab3').html(data);
$('#tab3').addClass('active');
$('.tab_3').addClass('active');
}
});
}
}
});
return false;
});
This problem was near impossible to google, so I'll add some search terms here:
Asp MVC Ajax.BeginForm()
causes exponential postbacks after every submit.
I know this question is not about MVC, but I couldn't find another question to post the solution to.
Please ment with a link if you do find one. Thank you.
Solution:
For me I had included the <script>
tag inside my Partial-View (or the Element of my UpdateTargetID
).
I think the script was being sent over on every postback and piling up on the client/web browser.
Beats me what the internals of my browser does, but once I moved the Script outside of the Ajax.BeginForm()
, the repeated postbacks/submits stopped.
I should note, this particular script was initiating a submit after a time-interval had passed, which would explain why I hadn't noticed this behavior before with other scripts I had added inside my UpdateTargetID
.
I was getting double requests for each click and this was slowing down the application for each fetch
what you are doing was still "acceptable" #user4655002
Request Before restructuring code
you can get rid of this error by looking at the overall layout of your html code. put the requests out of the body prolly at the footer.This worked for my case
It may not be possible to post your whole project on SO but i hope this practical advice helps.
Request after restructuring code