JavaScript event handler isn't called on appended button - javascript

I have form where I can add options and add new fields of options. I am using JQuery for this. The problem is that the remove button of added fields doesn't work.
Here's my form:
Logic
I click Add New button and new row will add Working
I click Remove it has to remove that row Not Working
$(function() {
//add row for options
$("#addnewoptinrow").click(function(e) {
e.preventDefault();
$('.newrow').append('<div class="row mt-3 newrowadded"><div class="col-md-8"><input name="options[]" type="text" class="form-control" placeholder="Option Name"></div><div class="col-md-2"><input name="optionsprices[]" type="number" class="form-control" placeholder="Price"></div><div class="col-md-2"><button type="button" class="removerow btn btn-danger" id="removerow">Remove</button></div></div>');
});
//Remove the row
$('.removerow').on('click', function(e) {
e.preventDefault();
$('.newrowadded').closest("div.row").remove();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<div class="col-md-8">
<input name="options[]" type="text" class="form-control" placeholder="Option Name">
</div>
<div class="col-md-2">
<input name="optionsprices[]" type="number" class="form-control" placeholder="Price">
</div>
<div class="col-md-2">
<button class="addnewqtydiscmsgsave btn btn-primary" id="addnewoptinrow">Add New</button>
</div>
</div>
<div class="newrow"></div>
Any idea how to fix that remove action?

There are two issues in your code:
the call to on() is missing the "selector" argument, which means that no elements dynamically added in future will have the click event boundy
your remove logic needs to be executed relative to the button being clicked
Try the following changes in your .removerow click handler:
/*
Bind the click handler to all elements dynamically added that match the
.removerow selector
*/
$('body').on('click','.removerow', function(e){
e.preventDefault();
/*
Explaination:
1. from "this" remove button being clicked,
2. select the closest ".newrowadded" and,
3. remove it
*/
$(this).closest(".newrowadded").remove();
});
See the snippet below for your a working example based off of your code:
$(function() {
//add row for options
$("#addnewoptinrow").click(function(e) {
e.preventDefault();
$('.newrow').append('<div class="row mt-3 newrowadded"><div class="col-md-8"><input name="options[]" type="text" class="form-control" placeholder="Option Name"></div><div class="col-md-2"><input name="optionsprices[]" type="number" class="form-control" placeholder="Price"></div><div class="col-md-2"><button type="button" class="removerow btn btn-danger">Remove</button></div></div>');
});
//Remove the row
$('body').on('click', '.removerow', function(e) {
e.preventDefault();
$(this).closest(".newrowadded").remove();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<div class="row">
<div class="col-md-8">
<input name="options[]" type="text" class="form-control" placeholder="Option Name">
</div>
<div class="col-md-2">
<input name="optionsprices[]" type="number" class="form-control" placeholder="Price">
</div>
<div class="col-md-2">
<button class="addnewqtydiscmsgsave btn btn-primary" id="addnewoptinrow">Add New</button>
</div>
</div>
<div class="newrow"></div>

The problem is that your code is only being executed on page load and at this time, your remove button is not yet created. You need to add an event listener to the remove button after your remove button has been created.

Button.removerow was added later. you can try this:
//add row for options
$("#addnewoptinrow").click(function(e) {
e.preventDefault();
$('.newrow').append('<div class="row mt-3 newrowadded"><div class="col-md-8"><input name="options[]" type="text" class="form-control" placeholder="Option Name"></div><div class="col-md-2"><input name="optionsprices[]" type="number" class="form-control" placeholder="Price"></div><div class="col-md-2"><button type="button" class="removerow btn btn-danger" id="removerow">Remove</button></div></div>');
//Remove the row
$('.removerow').on('click', function(e) {
e.preventDefault();
$('.newrowadded').closest("div.row").remove();
});
});

In oder to match your event listener to later created elements, you need to delegate it. In older JQuery versions it was done by the .delegate method, however, in recent versions this method is deprecated. Now you can delegate by ancestorCollection.on('query-selector', 'event', listener).
In your example something like
$('.newrow').on('.removerow', 'click', function(e){ /*...*/ })

The issue is that you are trying to bind actions on elements that are not yet created - you should use a more general binding as below:
$(function(){
//add row for options
$("#addnewoptinrow").click(function(e){
e.preventDefault();
$('.newrow').append('<div class="row mt-3 newrowadded"><div class="col-md-8"><input name="options[]" type="text" class="form-control" placeholder="Option Name"></div><div class="col-md-2"><input name="optionsprices[]" type="number" class="form-control" placeholder="Price"></div><div class="col-md-2"><button type="button" class="removerow btn btn-danger" class="removerow">Remove</button></div></div>');
});
//Remove the row
$(document).on('click','.removerow', function(e){
e.preventDefault();
$(this).parent().parent().remove();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="row">
<div class="col-md-8">
<input name="options[]" type="text" class="form-control" placeholder="Option Name">
</div>
<div class="col-md-2">
<input name="optionsprices[]" type="number" class="form-control" placeholder="Price">
</div>
<div class="col-md-2">
<button class="addnewqtydiscmsgsave btn btn-primary" id="addnewoptinrow">Add New</button>
</div>
</div>
<div class="newrow"></div>
Pay attention to the
$(document).on('click','.removerow', function(e){
line of code. This line appends the action to all of the '.removerow' elements, present and future. So when new elements are added with this class, they are automatically assigned this action (BTW, had to change your HTML from id="removerow" to class="removerow", to avoid duplicate ID's).
And please read this topic, it goes into more details of your issue.

Related

Multiple buttons in Bootstrap validator form

I have a simple form with multiple submit buttons. How do I change the java script to see, which button is clicked. Thanks
<form class="contact" role="form" data-toggle="validator" id="testform">
<div class="form-group">
<label for="inputName" class="control-label">Name</label>
<input type="text" class="form-control" id="inputName" name="inputName" placeholder="Cina Saffary" required>
<div class="help-block with-errors"></div>
</div>
<div class="form-group">
<button class="btn btn-success" type="submit" id="save1" value="save1">save1</button>
<button class="btn btn-success" type="submit" id="save2" value="save2">save2</button>
</div>
</form>
$('#testform').validator().on('submit', function (e) { (e.isDefaultPrevented()) {
alert("failure!");
} else {
// if save1 clicked, alert("save1 was clicked");
// if save2 clicked, alert("save2 was clicked");
}
});
You can get button value like this:
var val = $("button[type=submit][clicked=true]").val();
And you need to add one more event for button also
$("form button[type=submit]").click(function() {
$("button[type=submit]", $(this).parents("form")).removeAttr("clicked");
$(this).attr("clicked", "true");
});
DEMO
Reference: How can I get the button that caused the submit from the form submit event?

Jquery does not select the form element given an ID

I'm trying to submit a form with jquery, but it does not acknowledge that I submitted it when I click the "submit" button.
My html is as follows:
<form id="singleParam" role="form">
<div class="form-group">
<label for="sample_size">Number of samples needed</label>
<input name="choices[sample_size]" type="number" class="form-control" id="sample_size" placeholder="Enter desired number of samples">
</div>
<div class="form-group">
<label for="mode">Mode of the distribution (value most likely to be sampled)</label>
<input name="choices[mode]" type="number" class="form-control" id="mode" placeholder="Enter the likeliest value for your parameter">
</div>
<div class="form-group">
<label for="confidence">Confidence interval factor</label>
<input name="choices[confidence]" type="number" class="form-control" id="confidence" placeholder="Enter desired confidence interval factor">
</div>
<div class="form-group">
<input type="button" class="btn btn-primary btn-lg" id="submit" name="submit">
</div>
</form>
and JS is:
$('#singleParam').on('submit', function () {
alert('Form submitted!');
console.log('Form submitted!');
return false;
});
The alert() or console.log() in the loop do not work, meaning that jquery did not run the code on submit. What am I doing wrong? It might be worth mentioning that I am using bootstrap.
Change the button type from type="button" to type="submit"
EDIT:-
Make sure you are calling all your event handlers once the DOM is fully loaded by adding all the code inside dom ready event like:-
$(document).ready(function() {
// code here
});

How To Remove Dynamically Generated Div Using jQuery

I want to remove a dynamically generated div using jquery, remove button will be with every div. So when I click any remove button, it will remove that div from DOM.
<div class="form-group" id="drag">
<div class="col-md-2">
<input type="text" class="form-control" id="name1" placeholder="Name">
</div>
<div class="col-md-2">
<input type="text" class="form-control" id="eng1" placeholder="Description Eng">
</div>
<div class="col-md-2">
<input type="text" class="form-control" id="ar1" placeholder="Description Ar">
</div>
<div class="col-md-2">
<a id="remove" href="javascript:;" class="btn btn-sm red">
Remove
<i class="fa fa-close"></i>
</a>
</div>
</div>
If you would generate a div with inside the div a button, you can add the following function to let that button make the parent div disappear:
function removeParent()
{
//remove button click, remove the parent div from the dom
$(this).parent().parent().remove();
//in your specific case you want the parent parent div to be removed since the button is encapsulated by 2 divs.
}
This function you then need to add to the onclick listener of the button. Either by just setting it in the html onclick='removeParent()' or using javascript:
//gerenate div + button
mybutton.addEventListener('click', removeParent, false);
$('body').on('click', '#remove', function(){
$(this).closest('.form-group').remove();
});
But it's not correct to have more than one elements with the same id. recomment you to change ID to class
Try like below. Use class remove instead of id, because id should be unique.
$('body').on('click', '.remove', function(){
$(this).closest('.form-group').remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group" id="drag">
<div class="col-md-2">
<input type="text" class="form-control" id="name1" placeholder="Name">
</div>
<div class="col-md-2">
<input type="text" class="form-control" id="eng1" placeholder="Description Eng">
</div>
<div class="col-md-2">
<input type="text" class="form-control" id="ar1" placeholder="Description Ar">
</div>
<div class="col-md-2">
<a class="remove" href="javascript:;" class="btn btn-sm red">
Remove
<i class="fa fa-close"></i>
</a>
</div>
</div>

Remove textbox, hr and text when remove button is clicked

I am trying to remove the via textbox, remove button and horizontal line when the Remove button is clicked (as seen in the image below).
I've tried the following so far but it doesn't work:
$(document).ready(function() {
// Remove waypoints
$(".remove-waypoint-button").click(function() {
$(this).parent.closest('input').remove();
$(this).parent.closest('hr').remove();
});
});
Fiddle here
Thanks for your help.
You need to use prev() instead of closest().
Use
// Remove waypoints
$(".remove-waypoint-button").click(function () {
$(this).prev('input').remove();
$(this).prev('hr').remove();
$(this).remove();
});
DEMO
However I would recommend you to wrap input and button in a div, then you can use .parent() to remove all at once. Here's an example.
$(document).ready(function() {
// Remove waypoints
$(".remove-waypoint-button").click(function() {
$(this).parent('div').remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="waypoints">
<div>
<input type="text" class="form-control booking waypoint input-lg" placeholder="Via" />
<label class="remove-waypoint-button">Remove</label>
</div>
<div>
<input type="text" class="form-control booking waypoint input-lg" placeholder="Via" />
<label class="remove-waypoint-button">Remove</label>
</div>
</div>
A better approach would be to improve your mark up by grouping similar fields.
This improves the script too.
I hope this is what you expected.
$(function() {
$(".remove-waypoint-button").on("click", function() {
$(this).parent(".container").remove();
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="waypoints">
<input type="text" class="form-control booking waypoint input-lg" placeholder="Via">
<hr>
<div class="container">
<input type="text" class="form-control booking waypoint input-lg" placeholder="Via">
<label class="remove-waypoint-button">Remove</label>
<hr>
</div>
<div class="container">
<input type="text" class="form-control booking waypoint input-lg" placeholder="Via">
<label class="remove-waypoint-button">Remove</label>
<hr>
</div>
<div class="container">
<input type="text" class="form-control booking waypoint input-lg" placeholder="Via">
<label class="remove-waypoint-button">Remove</label>
<hr>
</div>
</div>
closest() works on the parent of the element. hr and input are not parent of label.
thanks

jQuery .on() issue, console.log() works but element interaction doesn't

I am using this code inside $(document).ready(function(){ ... }):
$('#flavours').on('click', '.toggle-quantity', function(e){
e.preventDefault();
var $quantity_percent = $(this).parent().find('.quantity_percent');
if($quantity_percent.is(':hidden')){
console.log("is hidden");
$quantity_percent.show();
}else{
console.log("is not hidden");
$quantity_percent.hide();
}
});
What's happening is the console.log() is working, but the $quantity_percent is not showing/hiding.
Additionally, if I add an alert('test') to the beginning of the function (just after e.preventDefault) this also doesn't work, but the console.log() continues to work (it correctly logs 'is not hidden').
EDIT: Relevant HTML markup:
<div id="flavours">
<div class="row flavour" id="flavour_1" style="display: block;">
<div class="form-group">
<div class="col-xs-12">
<fieldset>
<legend>Flavour 1</legend>
<div class="col-sm-4">
<label>Flavour Name</label>
<input type="text" value="" name="flavour_name[]" data-flavour-id="1" id="flavour_name_1" class="form-control autocomp" placeholder="Flavour name">
<input type="hidden" value="" name="flavour_id[]" id="flavour_id_1" class="form-control flavour_id">
<p class="flavour_info"></p>
</div>
<div class="col-sm-6">
<label>Flavour Quantity <span class="fa fa-filter"></span> <span class="hidden-sm">Switch to </span>drops per ml</label>
<div class="input-group" id="quantity_percent">
<input type="text" class="form-control" id="flavour_percentage_1" name="flavour_percentage[]" placeholder="Flavour Quantity">
<span class="input-group-addon">%</span>
</div>
<div class="input-group" id="quantity_drops" style="display: none;">
<input type="text" class="form-control" id="flavour_drops_1" name="flavour_drops[]" placeholder="Flavour Quantity">
<span class="input-group-addon">drops/ml</span>
</div>
<p class="flavour_recommended_percentage"></p>
</div>
<div class="col-sm-2">
<label> </label>
<button class="btn btn-danger btn-block remove-flavour"><span class="glyphicon glyphicon-remove"></span> Remove</button>
</div>
</fieldset>
</div>
</div>
</div>
$(this).parent() is a label element which doesn't have a child with .quantity_percent
Also quantity_percent is an id and not a class. Use the ID selector
So use
var $quantity_percent = $('#quantity_percent');
instead of
var $quantity_percent = $(this).parent().find('.quantity_percent');
Note: IDs must be unique in HTML
EDIT: as per OPs comments
I updated it to a class rather than ID (as it's on a dynamically growing list)
Usage
var $quantity_percent = $(this).closest('.col-sm-6').find('.quantity_percent');
The .parent() targets the <label> therefore it can't find .quantity_percent

Categories

Resources