I'm trying to create a table, populated by an ajax query where each row has a delete button next to it, so it can be easily removed.
However if I try to build the button inside an ajax query it doesn't seem to post correctly.
To ensure it wasn't the code inside the jquery click I created this simple function
$('.delbutt').on("click", function(event) {
var confirm = window.alert("good button pressing skills!");
return false;
});
The ajax query and div table filling is handled by this:
(function ajaxMapCalls() {
$.ajax({
url: mapgrabber,
dataType: 'json',
success: function(data, textStatus, xhr) {
$("#vcmaps").empty();
var output1 = "<table><tr><th>Customer</th><th>vCenter</th><th>Cluster</th><th>vSwitch</th><th></th></tr>"
$(data).each(function(i, el) {
var output2 = "<tr><td>" + el.customer + "</td><td>" + el.vcenter + "</td><td>" + el.cluster + "</td><td>" + el.vswitch + "</td><td><button class='delbutt'>delete</button></td></tr>";
output1 += output2;
});
$("#vcmaps").append(output1 + "</table>");
}
});
setTimeout(ajaxMapCalls, 2000)
})();
The table buttons are there it all builds fine but the button doesn't behave as expected, there's not a simple jquery popup and it seems to attempt to post server-side which it shouldn't be doing at this point.
So I tried putting a copy of the buttin inside the html.
Html of the relevant section below
<form action="#" method="POST" id="custVCassign"><div id="vcMenu"
class="flip"><h3>Assignment</h3></div>
<div class="panel">
Customer: <select class="select" id="custbag"></select><br>
vCenter: <select class="select" id="vCenter"></select><br>
Cluster: <select class="select" id="vCluster"></select><br>
Distributed switch: <select class="select" id="vSwitch"></select><br>
<button id="custvcdel" class="button2">Delete Cluster and Switch</button>
<button id="custvc" class="button">Add Cluster and Switch</button><br>
<button class='delbutt'>delete</button></form>
<div id="vcmaps"></div>
</div></form>
The button INSIDE the html works absolutely fine, it does the alert, but any buttons generated by the ajax into the div "vcmaps" don't behave correctly.
I wondered if it was because it was a div futher down and it was changing to a traditional post action so I wrapped the div in another form..
<form action="#" method="POST" id="custVCen"><div id="vcmaps"></div></form>
Still the same.
Any ideas what's going on here?
Your "click" event handler won't catch buttons that are created dynamically by the ajax call. They don't exist yet when the event handler is called, so it ignores them. And since you didn't specify a type="button" attribute for your dynamic buttons, they default to type="submit", which, if the button is inside a form, will cause your form to be submitted using a full postback when they're clicked (and there's no click handler to override this).
Use delegated event handling to get round this. You set the event on an element which will definitely exist when the event handler is called, and then tell it to delegate the events down to any elements which match the secondary selector at the time when the event fires. I don't know what element would be the lowest common ancestor of your buttons, so I've just used document as an example:
$(document).on("click", '.delbutt', function(event) {
See the "Direct and Delegated events" section here: http://api.jquery.com/on/ for more details.
Secondly, use preventDefault() to ensure there's no secondary postback triggered by the button. Put:
event.preventDefault();
as the first line of your "click" handler. See https://api.jquery.com/event.preventdefault/ for more info. This is more reliable than putting return false; at the end of your function, because it means there's no potential time gap between the event firing and the prevention of the default.
Related
I have an script in which I'm going to add a file XLS, once that I validate the file format, I close a bootstrap's modal and open another modal which is an confirmation window to see whether the user is sure to upload that file.
This confirmation window has a confirmation button, once clicked I want that execute me an function which it's going to run an AJAX to make the request to the server.
However, because of that, I had the following doubts:
Which of the 2 ways is better (and the most correct) to run the code and why?
Why is the click event of the first input file executed if there has not been an event change? I mean, I add a file and the event change is executed and I can make clicks many times as I want, is not it supposed that I must add another file so that I can run the function inside again?
Put an event inside an event, has it a name?
$(document).ready(function(){
//First input file
$(document).on('change','#file', function(){
let file = $(this);
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 1</button>';
$('#button').html(button);
$('#button').click(function(){
console.log('CLICK IN FIRST INPUT FILE!');
});
});
//Second input file
$(document).on('change','#file2', function(){
let file = $(this);
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 2</button>';
$('#button2').html(button);
});
$('#button2').click(function(){
console.log('CLICK IN SECOND INPUT FILE!');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="file" name="file" />
<div id="button"></div>
<div style="margin-top:20px"></div>
<input type="file" id="file2" name="file2"/>
<div id="button2"></div>
Put an event inside an event, has it a name?
It has, the name is Bad Idea. Let me Expain. What happens when you execute the following code.
$('#button').click(function(){
console.log('CLICK IN FIRST INPUT FILE!');
});
A click event is registered to the button. Once an event is registered, it will fire everytime no matter how many times you click.
When you put that code inside another event handler like the first example, it gets executed everytime the file-input changes and a new event handler is registered. So when you select a file, and then decide to change it, file-input changes twice and you get 2 click events registered. Now click on the button, you get 2 new console log printed by one click!!! Try it..
Why is the click event of the first input file executed if there has
not been an event change
Because that's how event handler works, you register once, they get fired everytime after that.
Which of the 2 ways is better (and the most correct) to run the code
and why?
Obviously not the first one, because it is a bad idea, Not the second one either. In case of second one you are attaching event to a division that will contain the button. So you don't need to click on the button, just click anywhere right side of the button, the event gets fired!!!
So if none of them is right, what can we do?
Do not generate button/any html element by javascript for such simple tasks. Do it with HTML, plain and simple.
Do not nest event handler into another i.e put one event handler inside another, it will complicate things. Just put all event handlers directly inside document.ready event of jQuery. document.ready only fires once.
When you need to control user action then show/hide your button or other html element by javascript based on required conditions.
My suggestion is doing something like this.
$(document).ready(function(){
// Hide the button at first
$('#button').hide();
// When File-input changes
$('#file').change(function(){
if(**the file-input has a file selected**){
$('#button').show();
}
else{
$('#button').hide();
}
});
// When Button Clicked
$('#button').click(function(){
// Do the action
});
});
Which of the 2 ways is better (and the most correct) to run the code and why?
I believe this is better:
//Second input file
$(document).on('change','#file2', function(){
let file = $(this);
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 2</button>';
$('#button2').html(button);
});
$('#button2').click(function(){
console.log('CLICK IN SECOND INPUT FILE!');
});
Mainly because it's more readable and easy to follow. There is no need to have the button click event set up AFTER the input has been changed. It is better to change the STATE of the button, as you are doing. Even better would be to hide/show the button like:
$('#button2').show();
And have it initially hidden with:
<div id="button2" style="display: none">Click me</div>
Why is the click event of the first input file executed if there has not been an event change?
In my test, this all worked correctly.
How is called this?
The change events should only be called when you click and assign a file to the input.
you are binding the same event multiple times to the same button object. binding the same event to the same object in another event that may reoccur will result in binding it over and over (stacks events and fire them and in this case "it" multiple times). binding an action to an event should happen only one time per object. and I see that you are binding the click event to the div instead of the button. maybe you need to consider dynamic binding using .on() like this
$(document).ready(function(){
//first file change event
$(document).on('change','#file', function(){
let file = $(this);
//handling empty selection
if(file[0].files.length == 0){
$('#button').html("");
return;
}
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 1</button>';
$('#button').html(button);
});
//second file change event
$(document).on('change','#file2', function(){
let file = $(this);
//handling empty selection
if(file[0].files.length == 0){
$('#button2').html("");
return;
}
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 2</button>';
$('#button2').html(button);
});
//first button dynamic event (doesn't stack)
$('#button').on('click','button', function(){
console.log('CLICK IN FIRST INPUT FILE!');
});
//second button dynamic event (doesn't stack)
$('#button2').on('click','button', function(){
console.log('CLICK IN SECOND INPUT FILE!');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="file" name="file" />
<div id="button"></div>
<div style="margin-top:20px"></div>
<input type="file" id="file2" name="file2"/>
<div id="button2"></div>
note that you need to handle not choosing a file (e.g. files count is 0) like in my code
Put an event inside an event, has it a name?
It does have a name. It's called "daisy chaining" and it's not a good idea.
not enough rep to comment
I've had cause to do this. I had the unpleasant task of mucking through 2 years of code written by one person with little maintenance or code discipline. I wanted to keep the code structure intact, so I daisy-chained click events to perform some enhancements.
To avoid some problems mentioned in the better answers above, simply remember to call $(selector).off("click") before binding the next event.
const mainevent = (e)=>{
e.preventDefault();
your event data
.then((e) => {
second event()
})
.catch((error) =>
alert(error.message))
};
}
I am using Jquery and Ajax for performing the action, I need after loading complete page, a code click on the every button automatically.
I used the following javascript code for click all the buttons in the end of my page. but it is not working.
<script type='text/javascript'>
document.getElementByClassName('sub').click();
</script>
Structure of my Page code
[JQuery]
[PHP]
[HTML]
[Javascript]
I set all the buttons type as "BUTTON", When I set
type="submit"
The Autoclick code only work on the first button, but with the "button" type it is not working with any of them.
If I click manually on that buttons they are working properly.
Please give any suggestion. Thank You.
Youre using the wrong function. Elements is plural in that method.
document.getElementsByClassName('sub');
Additionally, calling click on this NodeList will not work. You need to loop through and call the event on each index.
Also, you say you're using jQuery. To ensure your call happens after DOM ready, wrap your JS with $().ready().
Last, use the tools you've provided yourself, in this case jQuery, and select your element that way.
$(document).ready(function(){
$(".sub").click()
});
In jQuery you can trigger the click like
$( ".sub" ).trigger( "click" );
Because you retrieve a NodeList(as pointed out in the comments) :
$(document).ready(function () {
var butEl = document.getElementsByClassName('sub'),
count = butEl.length;
for (i = 0; i < count; i++){
butEl[i].click();
}
});
Also is getElementsByClassName
If you're trying to click on multiple different form submit buttons, it makes sense that the browser will POST for only one of them - one page can't simultaneously navigate to multiple different URLs.
Similarly, when you change type to button, none of the forms will be submitted, even though you're clicking on the buttons.
If you know what you're doing, you could always add submit event handlers to all of your forms, and submit them via ajax requests instead - which should allow multiple of them to be processed. Note you may need to work out some extra logic for displaying success/failure for each form to the user since the browser won't navigate you to any of the existing "submitted" pages.
$(document).on('submit', 'form', function() {
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
dataType: 'json',
data: $(this).serialize(),
success: function(data) {
// Add logic here for handling success for each form, if required
},
error: function(xhr, err) {
// Add logic here for handling errors for each form, if required
}
});
return false; // To stop the browser processing this form
});
With this method, your first attempt with type="submit" buttons should work - however I would encourage you to be as specific as possible with your element selectors for both the forms and the buttons you're trying to target.
I have three radio buttons and I want, by default, to have the "BOTH" location which has a value of 3 to be clicked on page load so that it will run my jQuery post function. The radio button is filled-in giving the appearance of being clicked, but the click is not happening to post my function. Once I change the radio button however, the code works fine.
This is my code:
$("input:radio[name='location'][value='3']").click();
$('input[name="location"]').change(function() {
var location = $('input[name="location"]:checked').val(); var category = getUrlVars()["category"];
$.post(
'db/functions/package_conf.php',
{category:category, location:location},
function(data) {
$('#package_info').html(data);
});
});
Would you try to register the event handle first before trigger the event? $("input:radio[name='location'][value='3']").click(); after the .change' event..
you may consider use the checked too, like $("input:radio[name='location'][value='3']").prop("checked", true).
but for my personally preference, any default state should be done before hand and not the in the script, for example initiate your radio DOM element to have checked property <input type="radio" value="3" checked />, and then onLoad script call the post directly (anyway POST is not designed for this purpose, just imagine POST as to save something, if you just want to get/query some data, GET would be more reasonable)
click was triggered before the change's event handler was regestered.
$('input[name="location"]').change(function() {
var location = $('input[name="location"]:checked').val(); var category = getUrlVars()["category"];
$.post(
'db/functions/package_conf.php',
{category:category, location:location},
function(data) {
$('#package_info').html(data);
});
});
$("input:radio[name='location'][value='3']").click();
$(window).on('load', (e) => { $("#test").focus() })
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="test" value="23" type="number" style="font-size:30px;width:150px;">
i am using a table with different rows and an edit button on each row.
This edit button creates a form using ajax / json to fill the form details depending on the row clicked.
The problem then comes when creating the ajax for this form.
Im using the same method as always, but for some reason the ajax submission is not working on this form and its just going to the process PHP page.
Im just wondering if this is because the form is not on the page when the javascript code for the ajax call is loaded?
So an example:
1) The page is loaded and included on that page is:
<script type="text/javascript" src="admin/js/showUserDetailsForm.js"></script>
<script type="text/javascript" src="admin/js/saveUserDetails.js"></script>
2) I click edit, and the showUserDetailsForm.js creates the form. The form is this:
$('<div id="admin-edituser-popup">'+
'<div id="login-popup-title">Edit User:<button id="closeedituserform">Close</button></div>'+
'<div id="login-popup-centre">'+
'<form class="editUserDetails-form" action="admin/process/saveUserDetails.php" method="POST">'+
'Editing Details for User:'+response.username+' , User ID:'+response.userID+
'<input type="hidden" name="userid" value="'+response.userID+'">'+
'<input type="text" name="username" value="'+response.username+'">'+
'<input type="submit" value="Save User">'+
'</form>'+
'</div>'+
'</div>').appendTo('body');
3) I click the submit button, and its correctly returns the JSON i am looking for (updateSuccess).
4) The form is not processed via ajax, its simply going to where its action is.
The code for the ajax call on save details is:
// JavaScript - Save user details
$(document).ready(function(){
// When the form is submitted
$(".editUserDetails-form").submit(function(){
$.ajax({
type: "POST",
url: "admin/process/saveUserDetails.php",
data: $(".editUserDetails-form").serialize(),
dataType: "json",
success: function(response){
if (response.updateSuccess) {
alert('Saved');
}
}
});
return false;
});
});
I cannot see any reasons why that its not working (cant find any errors with class names etc) and there is not errors in the javascript.
The only thing i am unsure of is the fact that the form is created AFTER the code is loaded?
Thanks!
For newly created DOM element handlers, you should use JQuery's on().
For your issue, you should just replace $(".editUserDetails-form").submit(function(){ with $("body").on('submit', '.editUserDetails-form', function(){
Last but not least, #Brunis is right - you should add event.preventDefault() to your method (event parameter is automagically injected)
If you want to intervene the default behaviour you should either
1. use e.preventDefault() in your onsubmit event callbackFunction or
2. use a "script" button that doesn't submit, eg. button type=button will not submit, but then you'll have to adjust your onsubmit event to just be an onclick event for that button.
Also, there's no need to have method and action in your form element when you don't want that to happen.
I'm trying to get my program to create a new button on form submit. I know I've done something wrong but don't know how to fix it. Here is my code:
$("#searches").append('<button id="recent-searches">' + textbox + '</button>')
then later on I have:
$("#recent-searches").on('submit', function() {
I think the second part of the code is where I went wrong. Any help would be awesome.
Thanks!
There is no submit event for a button, did you mean click or submit event on a form?
Try
$("#recent-searches").on('click', function() { // if you are biding this after appending the button.
else
$(document).on('click',"#recent-searches" function() { // if you are binding this prior to appending the button to the DOM. use $("#searches").on(... if that element is available all the time in DOM.
if #searches is a form then you would do:
$("#searches").on('submit', function(){...
You're creating a button #recent-searches which will receive, among others, the event click when you click on it. However it won't fire submit events because those are just for form elements when an input element of type submit is clicked.
So you'd have a form, let's say:
<form id="searches"> ... </form>
Where you are appending the button, maybe this way:
$("#searches").append('<input type="submit" id="recent-searches">' + textbox + '</input>');
, and then you'd do:
$("#searches").on("submit", function (e) { ... });
Or you can also have your button but bind a click event instead like so:
$("#recent-searches").on("click", function (e) { ... });
$("#recent-searches").on('submit', function() {
This is going to bind to the element matching the id recent-searches that event. If the element doesn't exist then jQuery will do nothing. You have to bind the event to the whole document(or to a parent which will contain that element with id recent-searches) and specify the ID, like this:
$(document).on('click', '#recent-changes', function() {
In this case I think that something like this should work:
$('#searches').on('click', '#recent-changes', function() {
Since #recent-changes is appended to that element.
Remember that the submit event is not going to be fired when you click that button, because it is not the submit button, you can use this code:
$("#searches").append('<input type="submit" id="recent-searches" value="' + textbox + '" />');