I have a table with some records in it and each of that records can be edited. I have a sidebar with edit form in it with the same inputs and the same submit button. When I try to execute the function on that button which will send an AJAX request, it executes as many times as many sidebars I opened before, when I need to update only that record which was actually edited.
That's the code:
// On Edit
$('.action-edit').on("click",function(e){
e.stopPropagation();
$(".add-new-data").addClass("show");
$(".overlay-bg").addClass("show");
const row = $(this).closest('td').parent('tr').first();
const agendaID = row.data('agenda_id');
const form = document.querySelector('#update_form');
const url = $(form).data('action_url').replace('.ID.', agendaID);
getAgendaInfo(agendaID);
$('.add-data-btn').on('click', function (e){
e.preventDefault();
console.log(agendaID); // displays IDs of all records where sidebar was opened.
const ajaxData = grabFormData();
editAgenda(url, row, ajaxData);
})
});
I think the issue is that you are adding new click event listener each time you show a new editor but you don't remove the previous event listener.
Try doing $('.add-data-btn').off() before the $('.add-data-btn').on('click'....
The problem you have is that your click handler is created whenever that .on() function is evaluated. The issue is that you execute that multiple times. Instead of that, you will need to perform a few steps for an elegant solution:
#1
Find a tag which exists before you populate your action-edit elements. In the worst case that would be body and I suggest that you need to start experimenting with
$(function() {
$('body').on("click", '.action-edit',function(e){
e.stopPropagation();
$(".add-new-data").addClass("show");
$(".overlay-bg").addClass("show");
const row = $(this).closest('td').parent('tr').first();
const agendaID = row.data('agenda_id');
const form = document.querySelector('#update_form');
const url = $(form).data('action_url').replace('.ID.', agendaID);
getAgendaInfo(agendaID);
$('.add-data-btn').on('click', function (e){
e.preventDefault();
console.log(agendaID); // displays IDs of all records where sidebar was opened.
const ajaxData = grabFormData();
editAgenda(url, row, ajaxData);
})
});
});
Note that this needs to run exactly once and will automatically create click handlers for you.
#2
Find the closest tag to your grid which already exists at the time the page is loaded and change the selector accordingly.
#3
Test, test, test
Related
We have a tabulator column definition , where one of them is a button created by a formatter
{title:"input", field:"blank", width:30, frozen:true, responsive:0,formatter:customFormatter2}
Into formatter we create a button
var customFormatter2 = function (cell, formatterParams) {
var $button=$('<button>').text('Hola')
$button.click(function(){
$(cell.getElement()).trigger('contextmenu')
})
return $button.get(0);
}
Also we have a rowContextmenu created into tabulator.
I want call to menu that tabulator shows when we do right click in any row.
I tried call a trigger from cell,from row... and I dont know if the event is accessible ,or I dont know do it.
Thanks
I don't user jQuery often, but I believe the only thing missing is preventing the propagation of the click event after the contextmenu event, which hides the menu. Something like this should work, but I also had to add pageX and pageY to my custom event, so that Tabulator could calculate where to display the menu. I am not sure how I would do this in jQuery.
$button.click(function(event){
event.stopImmediatePropagation();
$(cell.getElement()).trigger('contextmenu');
});
Or without jQuery and definitely works,
function customFormatter(cell, formatterParams){
const button = document.createElement('button');
button.textContent = "Hola";
button.addEventListener('click', (event) => {
event.stopImmediatePropagation();
const myEvent = new Event('contextmenu');
myEvent.pageX = event.pageX;
myEvent.pageY = event.pageY;
cell.getRow().getElement().dispatchEvent(myEvent);
})
return button;
}
Here is a full example without jQuery.
https://jsfiddle.net/nrayburn/guxkw394/101/
Be careful with this. Because we are creating a custom event, it doesn't contain all of the normal properties that a real event would. If Tabulator starts relying on different event properties, it would break this code. (Maybe you could copy the original event from the click and pass those properties into the custom event. Not really sure how to do that.)
This is how i populate the table
I'm having some trouble with the datatables plugin for jquery. The table is populated dynamically, I have 3 columns with text and a fourth column which consists of a delete and an edit button. For the edit button I have a modal, and if I confirm the changes, it does indeed change the specific line in the table.
However, if I click on several edit buttons and cancel, when I actually want to change one it changes all the previously canceled lines.
Here is the relevant code:
$("#example").on("click", ".edit-button", function() {
$("#edit-modal").modal("show");
saveChanges(this);
});
function saveChanges(k) {
$("#edit-confirm").click(function() {
$(".itm-loader-modal").show();
setTimeout(function() {editJob(k);},1000);
});
}
function editJob(currentButton) {
$(".itm-loader-modal").fadeOut("slow");
var editedName = $("#job-name").val();
var editedDescription = $("#job-description").val();
var editedCompany = $("#job-company").val();
var data = {
"name":editedName,
"description": editedDescription,
"company": editedCompany
};
var currentLine = $(currentButton).parent().parent().children();
currentLine.eq(0).text(data.name);
currentLine.eq(1).text(data.description);
currentLine.eq(2).text(data.company);
$("#edit-modal").modal("hide");
}
Hard to say for sure, but one think that looks wrong is that each time saveChanges is called, you register new event listener on #edit-confirm button.
Once that #edit-confirm is clicked, it will execute all the registered event handlers – one for each .edit-button click.
Instead, you probably want to have a single #edit-confirm click handler and find a way to pass the info about the line that's currently being edited to it.
Cheers.
so when you call saveChanges it assign event handler to "#edit-confirm", all those event handlers are executed at once,
to avoid it you should attach event handler to it via delegation or i think this quick fix should work
$(this).find('#edit-confirm').click(function() {
/...
})
I have a Wizard on my page, and for one of the WizardSteps I have some JavaScript to enable / disable controls based on radio button selection.
This works fine in the first instance, however I also have a button which adds a row to a grid (and that row has a Remove link). If I click the button, or the Remove option, then it does what I can only describe as a partial postback of the page and any disabled controls will now be enabled.
I've tried to catch anything on PostBack, but this doesn't actually get fired which is why I've described it as a partial one.
Is there an event in JavaScript that I can catch for this? I figure if I can catch an event then I could try and make the controls enabled states persist.
EG I've tried to put some code to catch when the state changes for the control itself, but this doesn't fire.
var myControl = document.getElementById('mainContentPlaceHolder_myWizard_myControl');
if (myControl != null) {
myControl.onchange = function () { DisableControl(this); };
}
function DisableControl(myControl) {
// This actually does a lot more, but this is just for the purposes of showing some code.
myControl.enabled = false;
myControl.disabled = true;
}
try this functions:
<script>
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(function() {
//start request
});
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function() {
//end request
});
</script>
I have a form like the following:
The forms id is 'filter' and I have a jquery onclick function which runs code by using the following line:
$(document).on('click', '#filter', function(){
//on click do the following
This works perfectly. However, I have now added a checkbox to the form. The rest of the form continues to work perfectly but the checkboxes are 'uncheckable'! (if they are set to be pre-checked they stay pre-checked, if they are set to be unchecked they stay unchecked).
The only thing I can think is that the jquery on click function is overriding the checking of the checkboxes. Would this be the case? I can rectify the problem by using blur rather than click but ideally the code would run on click, and in any case id like to understand what is going on! Any ideas?
EDIT
This is the contents of the click handler:
$(document).on('click', '#filter', function(){
//on click do the following
var formData = $(this).serialize(); //put the form names and values into an array called formdata
$.get('filtertest.php',formData,processData); //jquery ajax call
function processData(data){
if(data==1){
$('#content').html('<h2>There is ' + data + ' property available!</h2>');
$('#linky').show();
}
else if(data==0){
$('#content').html('<h2>There are no properties available, please expand your search options.</h2>');
$('#linky').hide();
}
else{
$('#content').html('<h2>There are ' + data + ' properties available!</h2>');
$('#linky').show();
}
}//end processData
return false; //stops the page redirect as per normal operation
});//end submit
Basically the click function looks up matching details from the form in a database and returns the number of matching rows to put in the processdata function
This line is preventing the checkbox from checking:
return false; //stops the page redirect as per normal operation
Using return false will stop event propagation AND prevent the default behavior. The default behavior of a checkbox is to check/uncheck itself when clicked. You might be able to fix this by changing it to:
e.stopPropagation();
This should let the default behavior continue, without propagating any other events that will fire afterwards.
Or you can just take it out if it is no longer needed (based on your comment).
The client is making a request to the server.
I need to take part of that request, and make the form button work with Ajax.
This piece of code works perfectly for links:
var pagination_render = function() {
var pagination = $('.pagination a');
pagination.each(function() {
$(this).click(function(event) {
load_server(this.href, '.houseindex');
return false;
});
});
};
pagination_render();
I tried numerous things for making the Ajax button work, and this is one of the tries:
var contact_user = function () {
$('.expanded').find('#submit').each(function() {
$(this).unbind('click');
});
$('.expanded').each(function() {
$(this).find('#submit').click(function(event) {
form_submit($(this).parent(), '.contactuser .msg');
return false;
});
});
}
Whenever there is a successful Ajax call, it goes through all of the expanded items, and then binds a click event.
Now, sometimes this code works, and sometimes it doesn't.. When it doesn't work, it disables other events (toggle links) I have set up.
It seems as if I need to wait a few ms for it to load the component into the DOM.. Do I?
So I get that when you call contact_user you:
First unbind any previous binded click events from the submit button. I see one possible problem there and is that you are looking for an id of #submit. You should only have one id in a single page. Therefore you only need to use $('#submit').each(...) or if you have several submit buttons in the page either use a class if there are several submit buttons inside an .expanded item or just use $('.expanded :submit')
Adding a custom event when clicking the submit button. Same thing, you can simplify this by $('.expanded :submit') or if you truly only have one button with an id of submit (quite confusing). Go with $('#submit').
In conclusion:
var contact_user = function(){
$('.expanded :submit').unbind('click');
$('.expanded :submit').click(function(){
form_submit($(this).parent(), '.contactuser .msg');
return false;
});
};
the :submit selector will select all <input type="submit" />.