Dynamic HTML buttons within the scope of Javascript ajax calls - javascript

I'm currently populating an HTML table to display users. I use calls to an API to serve my user data to the table, and Javascript to append the row to the table. The last entry in each row features a delete button, which is supposed to pass user data as a $put to a separate API endpoint to delete the user of the corresponding row:
//Existing adhoc-users table.
var adhocUsersHtml = "<div><table class='table table-striped'><tr><th>Section</th><th>Role</th><th>First Name</th><th>Last Name</th></tr>";
$.each(json.sections, function (index, section) {
$.each(section.enrollments, function(index, user) {
if (user.adhocEnrollment == true) {
adhocUsersHtml += "<tr><td>" + section.sectionTitle + "</td><td>" + user.roleName + "</td><td>" + user.firstName + "</td><td>" + user.lastName + "</td>"
+ "<td><button id='delete' class='btn btn-default' data-style='height: 30px; margin-top: 0;'>Delete</button></td></tr>";
}
});
});
adhocUsersHtml += "</table></div>";
return adhocUsersHtml;
What's the best pattern for scoping 'this' with the delete buttons?
Should I put a custom attribute on the button that holds the user id for that row, and then add an onClick to all delete buttons that grabs the id and preforms the $put?
Is it possible to add an onClick function right after declaring HTML before appending it to the DOM with Javascript?

Put the user id into a data attribute on the delete button and add a single event handler to the table to handle all delete button clicks.
<button class='delete-user-btn' data-id="myUserId">Delete</button>
$("#myTable").on("click", ".delete-user-btn", function() {
var id = $(this).attr("data-id");
//delete code goes here
});

firstly, you are going to have many buttons so attribute id='delete' isn't appropiate
I will put class "delete" instead without userId and register onClick Listener after all buttons rendered
and since each row represent a user, i will put id on each row
<tr data-val="{userID}">
....
<td><button class='btn btn-default delete' data-style='height: 30px; margin-top: 0;'>Delete</button></td>
</tr>
<script>$('.delete').on('click', function(e) {
var tr = $(e.target).closest('tr'),
id = tr.data('val')
... do your code
})</script>

Related

Jquery delete elements that were created using .after

I have a table in my html file which has the column header hard-coded:
<table id="debugger-table">
<tr>
<th>Attribute</th>
<th>Computed</th>
<th>Correct</th>
</tr>
</table>
Which I populate with values for row 2 onwards in a .js file using jquery:
tableString = '';
DEBUG_DATA.forEach(function(debug_line){
tableString += '<tr><td>' + debug_line['attribute'] + '</td><td>' + debug_line['computed'] + '</td><td>' + debug_line['correct'] + '</td>'
});
$('#debugger-table tr:last').after(tableString);
When the user performs a certain action I want to update the values. My question is how do I remove the text I've added, so that I can replace it with new text, instead of just appending the new values after the old ones.
I figure I could destroy the whole table and then create a new one with the column headers. Seems overkill though. Is there a way to refer back to the text added with .after, and delete it? thanks.
Store the addition into a jQuery object:
const rows = $(tableString);
('#debugger-table').append(rows); // Tip: this is better than
// $('#debugger-table tr:last').after(rows);
Then later remove it when needed:
rows.remove();

Enable/Disable an HTML Element With Dynamically Generated Names/Tags

I have a table in HTML where the ID is dynamically generated from a row counter:
$(table).find('tbody').append("<tr>name=\"tableRow\"</tr>"
+ "<td>"
+ "<select id=\"shapeSelect_" + rowCount + "></td>"
+ "<option onclick=\"sphereSelect()\" value=\"sphere\">Sphere</option>"
+ "<option onclick=\"cylinderSelect()\" value=\"cylinder\">Cylinder</option>"
+ "</select>"
+ "</td>"
+ "<td><input type=\"text\" id=\"altitude" + rowCount + "\"</td>"
+ "<td><input type=\"text\" name=\"maxAlt\" id=\"maxAltitude_" + rowCount + "></td>"
+ "</tr>"
I need maxAltitude to become disabled for input when sphere is selected. When cylinder is selected, it should become enabled for input.
Every example I find is pretty simple but requires knowing exactly what the ID is, where in my code it is dynamically generated. This is an example of what I'm finding:
$(#maxAltitude).prop("disabled", true);
How can I do this when maxAltitude will be something more like: maxAltitude_10? There may be 1-n rows in a table, and I need to specifically disable the max altitude in the row where the dropdown select was changed.
I've tried jQuery and javascript but can't seem to find a good way to do this:
<option onclick="shapeSelect()" value="sphere">Sphere</option>
<option onclick="shapeSelect()" value="cylinder">Cylinder</option>
function shapeSelect() {
var shapeSelects = document.getElementsByName("shapeSelect");
var maxAlts = document.getElementsByName("maxAlt");
for(var i = 0; i < shapeSelects.length; i++) {
switch(shapeSelects[i].value) {
case "sphere":
maxAlts[I].disabled = True;
break;
case "cylinder":
maxAlts[i].disabled = False;
}
}
}
With the above code I get: SyntaxError: unexpected token: identifier whenever shapeSelect() is fired.
I've modified the code as follows:
<table class="myTable" id="myTable"></table>
$(table).find('tbody').append("<tr>name=\"tableRow\"</tr>"
+ "<td>"
+ "<select id=\"shapeSelect_" + rowCount + "></td>"
+ "<option value=\"sphere\">Sphere</option>"
+ "<option value=\"cylinder\">Cylinder</option>"
+ "</select>"
+ "</td>"
+ "<td><input type=\"text\" id=\"altitude_" + rowCount + "\"</td>"
+ "<td><input class=\"maxAltitudeInput\" type=\"text\" id=\"maxAltitude_" + rowCount + "\" disabled></td>"
+ "</tr>"
$('#myTable').on('change','.shapeSelector',function(){
var shouldDisableInput = $(this).val() === 'sphere';
$(this).closest('tr').find('.maxAltitudeInput').attr('disabled',shouldDisableInput);
}
And still nothing happens when I change the shape selector dropdown.
EDIT:
Apologies on the naming mismatches. My dev machine is on an airgapped network and I was hand jamming the post here on Stack Overflow. The rowCount variable was being created and incremented in another function. I was trying to only put relevant code in the post for brevity.
I was missing a class from shapeSelector. That was the missing link. It works now!
jQuery actually makes this really easy by binding this to whichever element triggered an event.
For instance, instead of writing a generic function for when that value changes, you could use jQuery to bind an event listener to them:
$('#myTable').on('change','.shapeSelector',function(){
var shouldDisableInput = $(this).val() === 'sphere';
$(this).closest('tr').find('.maxAltitudeInput').attr('disabled',shouldDisableInput);
}
You'll notice a few things in this snippet:
The element we are binding the listener to is the table, not the individual row. That's because the row is dynamic, and we don't want to have to keep adding listeners every time we add a row. Instead we add it to the parent which is stable, but then we specify that we are interested in its children that match ".shapeSelector"
The listener relies on class names, not IDs, since we want to match multiple copies of them, not just a specific one. So you'd need to add those class names or a similar way of matching more than one item
Inside the callback function that runs, you'll notice a couple uses of this. jQuery has bound that to the element that triggered the event listener, in this case, the <select> control. So when we use this, we have to think of it from that perspective. We can get its value by $(this).val(), we can find its parentt with $(this).parent(), etc. In this case, I'm travelling up to the nearest tr, then from there down to that tr's input that I want to disable. You'd need to adjust a little depending on your dom.
Also note that this is a DOM element, not a jQuery result. That's why when we want to run more jQuery commands on it, we have to put it in $() again.
That's how I'd approach it. We don't have your entire code here, so you'll have to adjust a bit, but hopefully that pushes you off in the right direction.
EDIT
To be honest, there were a lot of naming mismatches and things that didn't line up. For instance, you were attempting to append onto a tbody tag, but that tag didn't exist. You were using a rowCount variable, but didn' ever set that up or increment it. The select tag sill didn't have the class name you were trying to use.
I suggest you look at your code piece by piece, ask yourself what you're telling the browser to do, and then do that instruction in your mind to make sure the computer can do it.
HTML:
<table class="myTable" id="myTable"><tbody></tbody></table>
JavaScript:
var rowCount = 0;
function addRow(){
$('.myTable tbody').append(`<tr name="tableRow">
<td>
<select class="shapeSelector" id="shapeSelect_${rowCount}">
<option value="sphere">Sphere</option>
<option value="cylinder">Cylinder</option>
</select>
</td>
<td><input type="text" id="altitude_${rowCount}" /></td>
<td><input class="maxAltitudeInput" type="text" id="maxAltitude_${rowCount}" disabled></td>"
</tr>`);
rowCount++;
}
$('.myTable').on('change','.shapeSelector',function(){
var shouldDisableInput = $(this).val() === 'sphere';
$(this).closest('tr').find('.maxAltitudeInput').attr('disabled',shouldDisableInput);
});
addRow();
addRow();
addRow();
https://jsfiddle.net/32vnjq81/

How to prevent appending multiple times in the table, Once It forcing to double click multiple times the table row using Jquery?

I have module appending the result of response to the other table. looking forward I found a solution in my module. however I found problem on that i will give to you guys the scenario what the problem it does.
First Scenario:
User will choose what condiment he wanted to click, Looking forward Ex. User 1 choose the Second table row, the Condiments *LG FRIES.
Second Scenario:
In the first scenario user choose the *LG FRIES, as you can see here modal will open and the result of response will append to the table B.
Third Scenario: Well First and Second scenario look works and good, but here I will show you, how does appending will multiply in the table once i force double click the table row of *LG FRIES.
So now i will let you show my codes.
This is my function for getting the result of clicking the of table row then the result will append to the table B.
$('table#noun_chaining_order').on('click','tr.editCondiments',function(e){
var allow_to_open_condiments_conditional = $(this).closest("tr").find(".allow_to_open_condiments_conditional").text();
if(allow_to_open_condiments_conditional == 'Yes') {
$('.conditional_table_hidden_noun').hide();
$('.conditional_table_hidden_condiments').show();
$('table#noun_chaining_order tr').removeClass('selected');
$(this).addClass('selected');
var find_each_id_condiments = $(this).find('td.condi_section_id').text();
$("table#customer_table_update_chain_order tbody").html('');
$('#customer_modal_update_chain_order').modal('show');
$.ajax({
url:'/get_each_id_section_condiments',
type:'get',
data:{find_each_id_condiments:find_each_id_condiments},
success:function(response){
var get_each_section = response[0].condiments_table;
$.each(get_each_section, function (index, el) {
var stringify = jQuery.parseJSON(JSON.stringify(el));
var cat_condi_screen_name = stringify['cat_condi_screen_name'];
var cat_condi_price = stringify['cat_condi_price'];
var cat_condi_image = stringify['cat_condi_image'];
var image = '<img src=/storage/' + cat_condi_image + ' class="responsive-img" style="width:100px;">';
// $('#edit_chainingBuild').append("<tr class='clickable-row'><td>" + Qty + "</td><td class='clickable-row-condiments'>" + Condiments + "</td><td>" + Price + "</td><td style='display:none;' data-attribute-chain-id="+menu_builder_details_id +" class='data-attribute-chain-id'>"+menu_builder_details_id+"</td></tr>");
$('table#customer_table_update_chain_order tbody').append("<tr class='edit_condimentsClicked' style='font-size:14px; border:none;'><td class='edit_condimentsScreenNameClicked'>" + cat_condi_screen_name + "</td><td class='edit_condimentsScreenPriced'>" + cat_condi_price + "</td><td>"+image+"</td></tr>");
});
},
error:function(response){
console.log(response);
}
});
}
else
{
}
});
So the question will be, How to stop appending multiple times once I force double click the table row?
I see simple solutions here.
When you appending cart item, you can add that item ID from database
to the element. And before appending check if an item from response
doesn't exist in BODY.
Another solution will be just after you click append - hide that CTA
(button)to prevent it from another click.
Check your database for multiple records.
Anyways, please check when you do ajax request? after click?
Have you tried to debug your code with breakpoints? or console?

jquery: set the value of the added input with the append one at a time

With ajax, I add to a table one row of an item and therefore imposed the id value of an input (connected to a button that opens the php page with that specific item card).
The first entry (via append) is ok: the item is properly displayed and its id is properly assigned to the button
but when I add (via append) the following item in the subsequent lines, the id of the setting of these successive item does not work: each of these id has the value of all ( id_item = 1 & id_item = 2 & id_item = 3 ... ).
The append function does not retain the attributes settings?
Enclosed is the code that I use:
$.ajax({
...
success: function(id_item) {
var row_appended = (
'<tr class="class_tr" id="id_tr">' +
'<td width="90%">NEW ITEM</td>' +
'<td width="10%">' +
'<form method="GET" action="see_item.php">' +
'<input type="hidden" name="id_item" class="id_item" value=0>' +
'<button type="submit" class="button_change_item" title="see item">See item</button>'+
'</form>' +
'</td>' +
'</tr>'
);
//$(append).appendTo('table#tabella_elenco_clienti');
//OR:
$("#table_items").last().append(row_appended);
//$('table#table_items tr :input[value="0"]').val(id_item);
//OR:
$('#table_items tr:last :input.id_item').val(id_item);
},
error: function(){
alert("Error!!!");
}
});
Your problem it's not on the append function it's on the jquery or jscript execution.
Those append id's don't exists for .click because they are not on the dom
so you should use a jquery .live|.on jquery action instead of .click
juqery.on

jQuery selector unable to find table row class

Given an array of strings returned from an sql query, I am appending the data as rows into my html table via javascript:
loadUsers: function()
{ .
.
.
function displayUsersOnTable(response)
{
for(var i = 0; i < response.results.length; i++)
{
var contact = response.results[i];
var $newRow = $('<tr class="user-row">' +
'<td>' + contact.full_name + '</td>' +
'<td>' + contact.email + '</td>' +
'</tr>')
.data('user', contact);
$userTableBody.append($newRow);
}
}
}
Inside a different function that is called after loadUsers is called, I have this:
$('.user-row').click( function() {
window.alert("CLICKED");
});
When I run my site it won't register the click event. If I select the classes from my table row or table header it runs fine. I suspect the problem involves the fact that the table rows are dynamically generated. When I inspect element everything is in place. What am I missing?
try:
$(document).on('click', '.user-row', function() {
window.alert("CLICKED");
});

Categories