query click event for buttons inside a foreach loop - javascript

I am populating a data-table from a model using a foreach loop:
#foreach(var item in Model)
{
<tr>
<td style="display: none">#item.Id</td>
<td>#item.Name</td>
<td>#item.Description</td>
<td>
<div class="btn-group">
<button type="button" class="btn btn-default" data-dismiss="modal">Update</button>
<button type="button" data-id=#item.Id id="Delete" class="btn btn-danger" data-dismiss="modal">Delete</button>
</div>
</td>
</tr>
}
Each row of the table has an update and delete button.
I'm struggling to bind the buttons to a click event using jQuery.
Here is my script so far which is within the document ready function:
var table = $('#productTable').DataTable();
$('#productTable tbody').on('click', 'tr', function () {
var data = table.row(this).data();
alert(Product ID = ' + data[0] + ');
//Call delete function and pass in Id
});
This is understandably showing an alert anytime the user clicks the row. How to I get it to only fire when the delete button is clicked?
Thanks in advance for any help.

You can take doutriforce suggestion and bind the events to a class, for example:
$("#productTable tbody").on("click", ".btn-update", function() {
// Your update code here
// Use $(this) to access the button that triggered this event
}
$("#productTable tbody").on("click", ".btn-delete", function() {
// Your delete code here
// Use $(this) to access the button that triggered this event
}
I've used: $("#productTable tbody").on("click", ", function); because it also works for dynamically added elements (in this case, table rows).

Based on the documentation here, it looks like you need to edit the selector that you bind the click event too, like this:
$('#productTable button#Delete').on('click', function () {
var data = table.row(this).data();
alert(Product ID = ' + data[0] + ');
});

const medias = document.querySelectorAll('._23fpc');
for (let i=1; i<medias.length; i++) {
const media = medias[i];
const firstClickable = media.querySelectorAll('._1JX9L')[1];
if(firstClickable) {
window.setTimeout(() => firstClickable.click(), 50);
}
}
I edited the code copied from the internet, it kind of works
PS:I know nothing about coding

Related

How can I set click function on my current element?

I am trying to dynamically set a click function on a role=button element I add from jQuery. Here is my code:
box_resources.forEach(function(box){
var title_button = '<a class="btn btn-primary btn-xs" style="margin:5px">' + title + '</a>';
var $list_item = $(title_button);
$list_item.click(function() {
console.log("hello");
});
$("#resources-master-list").append(title_button);
});
It seems this way does not work. Does anyone have any idea? Thanks!
Instead of adding a new click handler each time you add an item to the DOM, try using event delegation. To understand how this works, check out the link for more information.:
$(document).on("click", "[role='button']", function () {
alert("i'm clicked");
});

Bind click event not work in dynamic created elements

I call call ajax and when success i build button elements.
Like this :
...
.done(function(data) {
$('#data-message').empty();
// console.log(data);
$('#total_notification_msg').html(data.total);
$.each(data.data, function(index, value) {
// console.log(value);
var redirectRead = '{{ route("adm1n.message.show", ":id") }}'
redirectRead = redirectRead.replace(":id", value.id);
var pesan = value.message.substr(0,100);
$('#data-message').append('<button id='reply' class='btn btn-default btn-xs' style='margin-top:5px;'>Reply</button>");
});
})
...
But, i can't add click event on #reply button.
I already using on or click event :
$(document).on('click', '#reply', function() {
alert('Reply here');
});
// or this ...
$('#reply').click(function() {
alert('Reply here');
});
But it still not works.
Please help, thank you ^^
You need to use quotes properly when creating elements using string.
$('#data-message').append('<button class="reply btn btn-default btn-xs" style="margin-top:5px;">Reply</button>");
And use Event Delegation using .on() delegated-events approach, when generating elements dynamically
$('#data-message').on('click', '.reply', function() {
alert('Reply here');
});
Since Identifiers must be unique, use class instead.
You need to change two things:
correct quotes.
change id to class.
$('#data-message').append("<button class='btn btn-default btn-xs reply' style='margin-top:5px;'>Reply</button>");
//-----------------change here-----------------------------------^^^^^
Because you are in loop and you are duplicating same ids.
change your event binding to class:
$(document).on('click', '.reply', function() {
alert('Reply here');
});

backbone.js remove item from series

I am currently learning backbone.js and am wondering about removing an item from a series. I am working on the infamous recipe app and am creating step by step directions within textareas. I want to be able to remove one textarea without removing all of them. the creation event is like this:
"click #btnAddDirection": "addNewDirection"
addNewDirection: function (ev) {
ev.preventDefault();
this.directionCount++;
this.render(this.directionCount);
},
and my remove looks like this:
'click .subDirection': 'subDirection'
subDirection: function () {
this.$el.remove();
}
the issue I have is that when I click the [-] button all of the directions are removed rather than a single one. I am thinking I need to pass some sort of identifier in for the direction. Any help would be appreciated. Thanks.
here is the entire Direction Control View:
// The Direction Control View
var DirectionControl = Backbone.View.extend({
render: function (directionCount) {
if (directionCount == null) {
directionCount = 1;
}
var that = this;
var directions = new Directions();
var completeDirections = _.invoke(directions, 'fetch');
$.when.apply($, completeDirections).done(function () {
var template = _.template($('#direction-control-template').html(), { directions: directions.models, directionCount: directionCount });
$('.tblDirections').each(function () {
$(this).find('.addDirection').remove();
$(this).find('.newDirection').text('');
});
$(that.$el).append(template);
});
},
events: {
"click #btnAddDirection": "addNewDirection",
'click .subDirection': 'subDirection'
},
directionCount: 1,
addNewDirection: function (ev) {
ev.preventDefault();
this.directionCount++;
this.render(this.directionCount);
},
subDirection: function () {
this.$el.remove();
}
});
A Backbone best practice in this type of situation would be to give each direction its own individual View. Then, if you create an event within the Direction view, it will only trigger on elements within that view.
On your callback after the directions are fetched, you could try to loop through each in directions and create a new DirectionView view:
DirectionView = Backbone.View.extend({
events: {/*put click events for the individual direction here*/}
render: function(){/*render to this.el */ return this}
})
after you create the new DirectionView, you can render it to the main view you already have:
$(that.$el).append(directionView.render().el);
Your subDirection function will receive an event object in its parameters- you can use this to remove the correct direction. I suggest adding an id for each direction, but if you aren't worried about duplicates you could just pretend the content of the direction is the id. Example:
subDirection: function(event){
var $direction = $( event.currentTarget ).siblings('.direction-container');
var directionId = $direction.text();
// loop through the model's directions until you find the corresponding direction
// then remove that from the directions array
this.render(); // re-render the view
}
This is more of a jQuery-esque solution - not the Backbone best-practice like #Kyle R's, but this will accomplish what you're looking for.
what ended up working was to add data-index to the item in this fashion.
<!--Table for Direction entry control -->
<script type="text/template" id="direction-control-template">
<table class="tblDirections" id="idx_<%= directionCount %>">
<tr>
<td class="Directionlabel">Step # <%= directionCount %><input type="hidden" name="DirectionStep" value="1" />:</td>
<td class="Direction"><textarea id="Direction" rows="5" cols="70"></textarea><br></td>
<td>
<button type="button" id="btnAddDirection" class="btn btn-success btn-xs addDirection">+</button>
<button type="button" id="btnSubDirection" class="btn btn-danger btn-xs subDirection" data-index="idx_<%= directionCount %>">-</button>
</td>
</tr>
</table>
</script>
the control looks like this:
subDirection: function (ev) {
ev.preventDefault();
var currentTarget = $(ev.currentTarget);
var idx = currentTarget.data("index");
console.log("got index of " + idx);
$("#" + idx).remove();

Get a field with jQuery when a button is clicked

I have a table full of appointments. Every appointment has two buttons. One for canceling the event, one for accepting it.
I am struggling to get the appointmentId in the jQuery function when I click on a button. Can you please give me a hint how to do this? The appointmentId is in the table as a hidden input field.
// my html code
<tr>
<td align="left">
<input type="hidden" name="appointmentId" value="234">
John Smith - 14.03.2013 at 9 o'clock
</td>
<td align="right">
<input type="button" id="acceptEvent" class="acceptEvent" value="Accept">
<input type="button" id="cancelEvent" class="cancelEvent" value="Cancel">
</td>
</tr>
// my jQuery code
$("body").delegate('.acceptEvent', 'click', function() {
console.log('accept event clicked');
// get the appointmentId here
});
$("body").delegate('.cancelEvent', 'click', function() {
console.log('cancel event clicked');
// get the appointmentId here
});
Use closest to grab the parent tr element, then select your hidden field.
The reason that this is the correct answer is because it takes the context of the click event with $(this). Then it travels up the DOM tree to your root table row element and selects the child by name. This ensures that you are always in the correct row.
EDIT: I know you already selected an answer, but this was really bothering me that it wasn't working properly. I had to walk down twice using .children() to get it to work though you could also use .find('input[name="appointmentId"]'). Even though you've already selected your answer, I hope this will help you.
$('.acceptEvent').click(function() {
var myVal = $(this).closest('tr').children().children().val();
});
$('.cancelEvent').click(function() {
var myVal = $(this).closest('tr').children().children().val();
});
In the click function, you have access to the button that was clicked with this so you can do:
$("body").on('click', '.cancelEvent', function() {
var input = $(this).closest('tr').find('input[name="appointmentId"]').val();
});
Assuming you have no other IDs or classes to key off of, you can use jQuery's Attribute Equals Selector in reference to the clicked button's parent tr element:
$('.acceptEvent').click(function() {
// get the appointmentId here
var appointmentId = $(this).closest('tr').find('input[name="appointmentId"]').val();
});
I'll do it like that :
$("body").on('.acceptEvent', 'click', function() {
var id = $('input[name="appointmentId"]').val();
//Or search in the parent <tr>
var id = $(this).parent().find('input[name="appointmentId"]').val();
console.log('accept event clicked');
console.log('Id is ' + id);
});

Create a jQuery event after adding HTML element dynamically

I have a small script that creates new HTML form elements when a link in clicked via jQuery:
Javascript
var counterx = 2;
var counter = 2;
$(document).ready(function(){
$("#addMoreRcpt").click(function(){
if (counterx>10){
alert("Only 10 reciepients are allowed");
return false;
}
var newTextBoxTr = $(document.createElement('tr')).attr("id", 'RcptEml_' + counter);
newTextBoxTr.append("<td><input type="button" id="txtRcptID_'+ counter + '"></td><td><input type="button" value="Search" id="SearchItem_'+ counter + '">
</td>");
newTextBoxTr.appendTo("#RcptGroup");
counter++;
counterx++;
});
});
HTML
<table border=1>
<div id="RcptGroup">
<tr>
<th>1</th>
<th>2</th>
</tr>
<div id="1">
<tr>
<td><input type="text"></td>
<td><input type="button" value="Search" id="SearchItem_1"></td>
</tr>
</div>
</div>
</table>
<br /><a id="addMoreRcpt" href="#" >Add row</a>
Now for each newly created HTML form, I need to create a new jQuery event so that "Search button" will properly function. Here is the jQuery for the search button:
$("#searchItem_1").on('click', function() {
$("#bg").fadeIn(400, function() {
$("#modal").fadeIn(400);
});
});
$("#modal img").on('click', function() {
var text = $(this).siblings('.descr').text();
$("#modal").fadeOut(400, function() {
$("#bg").fadeOut(400, function() {
$("#txtRcptID_1").val(text);
});
});
});
You see, the script above refers to search_Item_1 button and textbox with id txtRcptID_ID. What I need to accomplish is to create that above script every time a the "Add Row" button is clicked.
But it also needs to have correct seatchItem_# and txtRcpt_# which corresponds to the counter number when a new element is created.
For example: when I click Add Row, and the counter currently at 3, then the script adds new element with id="txtRcptID_3" AND creates a new jQuery event starting like this $("#searchItem_3").on('click', function() {
I have tried and tried and tried but without success. Anyone can help?
EDIT **
I added the following code and got pretty close, but there is still a problem with adding the value from the modal window into the text field. I added an alert function to see the value of the counter, but it mysteriously increases by one when clicking the search button:
newTextBoxRow.appendTo("#RcptGroup");
newTextBoxRow1.appendTo("#RcptGroup");
alert("ID number:"+counter);
$("#searchItem_"+counter).on('click', function(ev){
$("#bg").fadeIn(400, function() {
$("#modal").fadeIn(400);
});
alert("ID number:"+counter);
});
$("#modal img").on('click', function(ev) {
var text = $(this).siblings('.descr').text();
$("#modal").fadeOut(400, function() {
$("#bg").fadeOut(400, function() {
$("#txtRcptID_"+counter).val(text);
});
});
});
counter++;
counterx++;
EDIT 2 **
Here is another try. I changed the id of the search text field to "txt_searchItem_'+ counter +'". And added this code. It functions, but still a problem though. When clicking on an image, it updates ALL text fields instead of just the one that triggered the modal window.
$(document).on('click', '.searchItemBtn', function(ev){
var getID = $(this).attr("id");
alert("ID number:"+getID);
$("#bg").fadeIn(400, function() {
$("#modal").fadeIn(400);
});
$(document).on('click', '#modal img', function(ev
var text = $(this).siblings('.descr').text();
$("#modal").fadeOut(400, function() {
$("#bg").fadeOut(400, function() {
$("#txt_"+getID).val(text);
});
});
});
});
If you want to make on method to attach handlers to elements dynamically created, you should use it like this:
$(parent_selector).on('click', child_selector, function(ev){
// do stuff on click
});
So, in your case, I would add a class to the buttons you are creating, besides the id:
newTextBoxTr.append('<td><input type="button" id="txtRcptID_'+ counter + '"></td><td><input type="button" value="Search" class="button_class" id="SearchItem_'+ counter + '">');
and would attach the handler like this:
$(document).on('click', '.button_class', function(ev){
// do stuff
});

Categories

Resources