Dinamically creating table and apend a subtotal row at the end - javascript

I'm creating a table with an Ajax Query on a modal hide event with this code.
$('#modalarticulos').on('hidden.bs.modal', function () {;
sel_articulos = $("input[name='check_art']:checked").map(function ()
{
return this.value;
}).get();
console.log(sel_articulos);
$("#sel_articulos tbody").empty();
ii =0;
var tbody = $('#sel_articulos tbody');
$.each(sel_articulos, function(ii, sel_articulo) {
var tr = $("<tr id=artrow["+ii+"]>");
$.ajax({
type: 'POST',
url: "<?php echo $_SERVER_ADDR . PUBLIC_PATH .'presupuestos/buscart/'; ?>",
data: { 'id':sel_articulos[ii]},
dataType: "json",
success: function(response) {
$("<td id='id["+ii+"]'>").html(response["id"]).appendTo(tr);
$("<td id='tipart["+ii+"]'>").html(response["tipart"]).appendTo(tr);
$("<td id='codart["+ii+"]'>").html(response["codart"]).appendTo(tr);
$("<td id='desart["+ii+"]'>").html(response["desart"]).appendTo(tr);
$("<td id='canart["+ii+"]'><input type='number' id='cantidad["+ii+"]' min='0' max='999' step='1' class='input-mini text-right cantidart' value='1'>").appendTo(tr);
$("<td id='precio["+ii+"]'>").html(response["precio"]).appendTo(tr);
$("<td id='subtot["+ii+"]'>").html("<label id='subtotal["+ii+"]' class='text-success subtotal'>"+response["precio"]).appendTo(tr);
tbody.append(tr);
},
error: function() {
alert('Error occurs!');
}
});
});
$('#sel_articulos > tbody').after(<tr><td></td><td></td><td></td><td></td><td><label class='subtotalg'>SUB-TOTAL</label></td><td></td><td><label id='subtotalsi' class='text-success subtotalg'>Subtotal</label></td></tr>;
})
question 1 the problem that i am facing is that i need the last row (the one being added after, the body) to be inside the body itself, now it is being created outside it and by consequence its not being cleared by the:
$("#sel_articulos tbody").empty();
Question 2 : in addition to that i would like to know if there is another way of arranging the creation of that table to make it more efficient. thank you.

$.after adds an element after the selected element. You need $.append which adds an element inside the selected element.
Do this:
$('#sel_articulos > tbody').append(<tr><td></td><td></td><td></td><td></td><td><label class='subtotalg'>SUB-TOTAL</label></td><td></td><td><label id='subtotalsi' class='text-success subtotalg'>Subtotal</label></td></tr>;
UPDATE
As per your comment, you need to add it after the rows are added. Just check if you're adding the last row first.
$.each(sel_articulos, function(ii, sel_articulo) {
$.ajax({
type: 'POST',
url: "<?php echo $_SERVER_ADDR . PUBLIC_PATH .'presupuestos/buscart/'; ?>",
data: { 'id':sel_articulos[ii]},
dataType: "json",
success: function(response) {
$("<td id='id["+ii+"]'>").html(response["id"]).appendTo(tr);
$("<td id='tipart["+ii+"]'>").html(response["tipart"]).appendTo(tr);
$("<td id='codart["+ii+"]'>").html(response["codart"]).appendTo(tr);
$("<td id='desart["+ii+"]'>").html(response["desart"]).appendTo(tr);
$("<td id='canart["+ii+"]'><input type='number' id='cantidad["+ii+"]' min='0' max='999' step='1' class='input-mini text-right cantidart' value='1'>").appendTo(tr);
$("<td id='precio["+ii+"]'>").html(response["precio"]).appendTo(tr);
$("<td id='subtot["+ii+"]'>").html("<label id='subtotal["+ii+"]' class='text-success subtotal'>"+response["precio"]).appendTo(tr);
tbody.append(tr);
// Check if added last row
if(ii == sel_articulos.length - 1){
$('#sel_articulos > tbody').append(<tr><td></td><td></td><td></td><td></td><td><label class='subtotalg'>SUB-TOTAL</label></td><td></td><td><label id='subtotalsi' class='text-success subtotalg'>Subtotal</label></td></tr>;
}
},
error: function() {
alert('Error occurs!');
}
});
});
However I would do what #Scottie said in the comments and get all the table data in one request, rather than one for each row. That would make this a lot easier because you could just append it after all the other ones have been appended.

You can use Deferred (and Promise) to manage it better, and indeed the ajax in jQuery would return a Promise like interface, so you can try:
var data = {};
var promise = $ajax.({
...
success: function (response) {
// Collect your data here
data['id'] = response['id'];
....
// This means success and the done callbacks in the deferred will be executed.
}
...
});
// The done call back will be executed after your ajax success callback is called
promise.done(function () {
// now use your data to create a table
...
});
Learn more about jQuery promise and defer:
https://api.jquery.com/promise/
https://api.jquery.com/category/deferred-object/

Related

Select Row from table with JSON values using JQuery

I have JSON data from an MVC controller with the values
[{"OperationName":"All","PrivilegeName":"Roles Crud"},{"OperationName":"Read","PrivilegeName":"Roles Read Delete"},{"OperationName":"Delete","PrivilegeName":"Roles Read Delete"},{"OperationName":"Read","PrivilegeName":"Roles Update"},{"OperationName":"Update","PrivilegeName":"Roles Update"}]
I have Displayed this JSON data into an HTML table using AJAX.
$(document).ready(function () {
//debugger;
$.ajax({
url: "/Home/GetOpPriv",
type: "GET",
contentType: "application/json; charset=utf-8",
data: "source={}",
dataType: "json",
success: function (data) {
var row = "";
$.each(data, function (index, item) {
row += "<tr id='trName_" + index + "'>";
row += "<td id='td_OpName" + index + "'>" + item.OperationName + "</td>";
row += "<td id='td_PrivName" + index + "'>" + item.PrivilegeName + "</td>";
row += "<tr>";
});
$("#table1").html(row);
console.log(data);
var source = [];
source.push(data);
console.log(source);
},
error: function (result) {
alert("Error");
}
})
});
I'm Trying to select individual rows from the table when I click the particular row, it should display its value in the alert box
But instead, it's displaying the entire table JSON data onClick.
What correction should I make to this JQuery Function?
$(document).ready(function () {
$("#table1 tr").click(function () {
debugger;
$('.selected').removeClass('selected');
$(this).parents('tr').addClass('selected');
})
});
As I understand your question, you want to display the selected row data, for this scenario, you can try like this
$("#table1 tr").click(function () {
$('.selected').removeClass('selected');
$(this).addClass('selected');
var _index = $(this).attr("id").replace("trName_", "");
var _currentSelectedRow = source[_index];
console.log(_currentSelectedRow);
});
And in ajax success block you are declaring the variable as
var source = [];
source.push(data);
Instead of this declare the 'source' variable as global variable and assign the json data to 'source' in ajax success block.
source = data;
If I understand your question correctly, then the solution is this:
$(document).ready(function () {
$("#table1 tr").click(function () {
$('.selected').removeClass('selected');
$(this).addClass('selected'); // remove .parents('tr')
})
});
By making the change above, this will cause only the row that the user clicks in #table1 (i.e. the row element corresponding to $(this) ) to have the selected class applied.
You are guaranteed to have $(this) inside of your click handler correspond to a table row element, seeing that the click handler is bound to tr elements via the #table tr selector. Hope this helps!

when adding row with jquery datatables - it's adding a row multiple times. Not just once

I am using jquery to send data through ajax to my DB, on success it shows a notification and adds a row to a datatable with the note / info the user just posted.
For some reason it's adding the row twice, instead of just once. Cant figure out why.
My code is :
<script type="text/javascript">
$(document).ready(function() {
$('#notestable').DataTable({
"paging": false,
"ordering": false,
"info": false,
"filter": false
});
$("#addnote").click(function(e) {
e.preventDefault();
var note = $("#note1").val();
var leadid = "<?echo $lead->leadid;?>";
$.ajax({
url: "/leads/addnote",
method: "POST",
data: {
note: note,
leadid: leadid
},
success: function(data) {
$('#closemodal12').trigger('click');
swal({
title: "Note added",
type: "success",
});
var notestable1 = $('#notestable').DataTable();
var lengthToCut = 23;
var short = note.substr(0, lengthToCut);
var i = 1;
var row = $('<tr>');
row.append('<td>' + short + ' </td>')
.append('<td><? echo $user->forename;?></td>')
.append('<td><? echo date('d / m / Y ');?> </td>')
.append('<td><? echo date('H: i ');?> </td>')
.append('<td><i class ="fa fa-eye"> </i></td>')
.append('<td><i class ="fa fa-trash-o"> </i></td>')
notestable1.row.add(row);
$('#notestable tbody').prepend(row);
},
error: function() {
alert("Slight problem");
}
});
});
});
</script>
Without seeing the markup that goes along with this, it's difficult to be sure, but I believe the problem lies with these two lines of code:
// Append row to notestable1 (already visible in DOM)
notestable1.row.add(row);
// (pre)Append the row again
$('#notestable tbody').prepend(row);
notestable1 appears to be a valid object, already inserted into the DOM, that you're appending the row to. You then append the row again using $('#notestable tbody').prepend(row).

Updating rows that are added dynamically using ajax

I hope I can explain my issue clearly.
I am running a function to get values from a database using ajax, and adding each result as a row in a table. This is so the user can delete or edit any row they want. I'm adding IDs dynamically to the columns and also the edit and delete buttons which are generated. So it looks like this:
My code:
function getstationdata(){
var taildata1 = $('#tailnumber2').val();
var uid = $('#uid').val();
$.ajax({
// give your form the method POST
type: "POST",
// give your action attribute the value ajaxadd.php
url: "ajaxgetstationdata.php",
data: {tailnumber:taildata1, uid:uid},
dataType: 'json',
cache: false,
})
.success(function(response) {
// remove all errors
$('input').removeClass('error').next('.errormessage').html('');
// if there are no errors and there is a result
if(!response.errors && response.result) {
var trHTML = '';
$.each(response.result, function( index, value) {
trHTML += '<tr><td><input type="text" value="' + value[2] + '"></td><td><input type="text" class="weightinputclass"value="' + value[3] + '"></td><td><input type="text" class="arminputclass"value="' + value[4] + '"></td><td><input type="text" class="momentinputclass" value="' + value[5] + '"></td><td><button id="updatecgbtn" onclick="updatecg()"class="editbuttonclass">Edit</button></td><td><button id="deletecgbtn" class="deletebuttonclass"">Delete</button></td></tr>';
});
$('#mbtbody').html('');
$('#mbtbody').html(trHTML);
var ID = 0;
$('.weightinputclass').each(function() {
ID++;
$(this).attr('id', 'weightinputboxID'+ID);
});
var ID = 0;
$('.arminputclass').each(function() {
ID++;
$(this).attr('id', 'arminputboxID'+ID);
});
var ID = 0;
$('.momentinputclass').each(function() {
ID++;
$(this).attr('id', 'momentinputboxID'+ID);
});
var ID = 0;
$('.editbuttonclass').each(function() {
ID++;
$(this).attr('id', 'editbutton'+ID);
});
var ID = 0;
$('.deletebuttonclass').each(function() {
ID++;
$(this).attr('id', 'deletebutton'+ID);
});
} else {
// append the error to the form
$.each(response.errors, function( index, value) {
// add error classes
$('input[name*='+index+']').addClass('error').after('<div class="errormessage">'+value+'</div>')
});
}
});
}
The code I have when adding the info is in a form and it looks like this:
$('#addstations').on('submit', function(e){
e.preventDefault();
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize(),
dataType: 'json',
cache: false,
})
.success(function(response) {
$('input').removeClass('error').next('.errormessage').html('');
if(!response.errors && response.result) {
$.each(response.result, function( index, value) {
chartdata4=(tailnumber3.value)
});
} else {
// append the error to the form
$.each(response.errors, function( index, value) {
// add error classes
$('input[name*='+index+']').addClass('error').after('<div class="errormessage">'+value+'</div>')
});
}
});
});
I searched a bit on the internet and found out that I can't add a form inside my table for each row which would have been easy to do and I can reuse my code which I use when adding new info.
So, can someone please point me in the right direction?
Here is the direction you could go
$('#formTable').on('click',"button" function(e){
var $row = $(this).closest("tr"), $form = $("#addstations");
var data = {
passenger:$row.find("passengerClass").val(),
weight :$row.find("weightClass").val()
} // no comma on the last item
data["type"]=this.className=="deletebuttonclass"?"delete":"edit";
$.ajax({
type: $form.attr('method'),
url: $form.attr('action'),
dataType: 'json',
cache: false,
})
...
I assume that the problem is that you want to add a form as a child of a table / tbody element to wrap your row. You cannot do that and the browser will most likely strip the form tags, leaving you with nothing to serialize.
There are different solutions for that, for example:
Build the data object manually in javascript when a button on a row is clicked;
Use a non-form grid solution for your layout.
Add each row in its own table and have the form wrap that table
The third solution is a bit of a hack, I would use the first or the second myself.

unable to delete newly added rows on the table with dataTable jquery

I have a html table that has a content came from a database by using ajax and php.
When i try to add a new row manually by filling all the inputs and click save button it will add the data to the table.
My problem is when i try to delete the newly added rows and click the delete button on that specific row it doesn't delete. But when i try to delete the rows that came from the database it is deleted from the html table.
script:
$.ajax({
url: 'process.php',
type: 'post',
data: {tag: 'getData'},
dataType: 'json',
success: function(data){
if(data.success){
$("#myTable2 tbody").empty();
$.each(data, function(index, record){
if($.isNumeric(index)){
var row = $("<tr />");
$("<td />").text(record.name).appendTo(row);
$("<td />").text(record.age).appendTo(row);
$("<td />").text(record.gender).appendTo(row);
$("<td />").html(record.action).appendTo(row);
row.appendTo("#myTable2 tbody");
}
})
}
var oTable = $('#myTable2').DataTable();
$("#myTable2 tbody .dltRow").bind( 'click', function(event) {
var row = $(this).closest('tr').get(0);
oTable.row(row).remove().draw();
oTable.row($(this).closest('tr')).remove().draw();
$(this).parent().parent().closest('tr').remove();
oTable.fnDeleteRow(oTable.fnGetPosition(row));
});
$('#Save2').on( 'click', function () {
var data = [
$('#name').val(),
$('#age').val(),
$("[name='gender']:checked").val(),
"<center><button type='button' class='btn btn-default dltRow'><i class='glyphicon glyphicon-trash'></i></button></center>"
];
oTable.row.add(data).draw();
});
}
});
use event delegation to attach events to dynamically added delete buttons.
$("#myTable2 tbody").on( 'click','.dltRow', function(event) {
var row = $(this).closest('tr').get(0);
oTable.row(row).remove().draw();
oTable.row($(this).closest('tr')).remove().draw();
$(this).parent().parent().closest('tr').remove();
oTable.fnDeleteRow(oTable.fnGetPosition(row));
});

Creating html table using javascript ajax calls in sequential order?

I am new to JavaScript. I am creating one table dynamically; I am facing a problem with the order of execution. I know JavaScript code won't execute sequentially, but what will be the work around?
First I will brief what I am trying to do.
1) loadList () -> I will call this method on click of load data button
here I will fire AJAX request to get data
2) using the result of above AJAX request, I am trying to create table rows
3) few table rows td having combo box, whose value to be filled using another AJAX call, passing the rowObject value
Below is my code:
var loadList = function(){
//ajax call
$.ajax({
url:"tworows.json",
type: "GET",
dataType : "json"
})
.done(function(data, textStatus, jqXHR){
generateTable(data);
});
};
function generateTable(data){
$("#gridTable").empty();
//create table header
var headertr = $("<tr><th>col1 </th><th>col 2</th><th>col 3</th><th>col 4</th><th>col 5</th><th>col 6</th><th>col 7</th></tr>");
//get table id from jquery
var tableelement = $("#gridTable");
//add header row to table
tableelement.append(headertr);
for(var i=0; i< data.links.id.length; i++){
tableelement.append(createRow(data.links.id[i]));
}
}
function createRow(rowObject){
//used to create combo box 1 based row 1 value
var combo1 = createCombo1(rowObject);
//used to create combo box 2 based row 1 value
var combo2 = createCombo2(rowObject);
var trElement = "<tr>"+
"<td><input type='text' name='col1name' value='"+rowObject.Number+"' onblur='handleInput(this)'/></td>"+
"<td><input type='text' name='col3name' value='"+rowObject.name+"'/></td>"+
"<td><input type='text' name='col3name' value='"+rowObject.quantity+"'/></td>"+
"<td>"+combo1+"</td>"+
"<td>"+combo2+"</td>"+
"<td><button>Del</button></td>" +
"<td><button>Add</button></td></tr>";
return trElement;
}
function createCombo1(rowObject){
var comboList = [];
//call ajax to get combo value
$.ajax({
url:"combo1data.json",
type: "GET",
dataType : "json",
async : false
})
.done(function(data, textStatus, jqXHR){
comboList = data.links.id;
});
var cmb1 = "<select name='cmb1' onchange='handlecmb1Change(this)'>";
for(var i=0;i < comboList.length; i++){
cmb1 +="<option value='"+comboList[i].id+"'>"+comboList[i].name+"</option>";
}
cmb1 += "</select>";
return cmb1;
}
function createCombo2(rowObject){
var comboList = [];
//call ajax to get combo value
$.ajax({
url:"combo2data.json",
type: "GET",
dataType : "json",
async : false
})
.done(function(data, textStatus, jqXHR){
comboList = data.links.id;
});
var cmb2 = "<select onchange='handlecmb2Change(this)'>";
for(var i=0;i < comboList.length; i++){
cmb2 +="<option value='"+comboList[i].id+"'>"+comboList[i].name+" </option>";
}
cmb2 += "</select>";
return cmb2;
}
Here row is creating first, after that control is going to createCombo methods. Because of this I am not getting combo boxes in td.
I want to create combobox based on first result of AJAX call; using the first result I need to call other 2 AJAX calls and populate them in the td combobox.
Please use below code block, this might be solve your problem. Your requirement need synchronous execution of methods, for this you need to use callback structure.
below is the code :
var loadList = function(){
//ajax call
$.ajax({
url:"tworows.json",
type: "GET",
dataType : "json"
})
.done(function(data, textStatus, jqXHR){
generateTable(data);
});
};
function generateTable(data){
$("#gridTable").empty();
//create table header
var headertr = $("<tr><th>col1 </th><th>col 2</th><th>col 3</th><th>col 4</th><th>col 5</th><th>col 6</th><th>col 7</th></tr>");
//get table id from jquery
var tableelement = $("#gridTable");
//add header row to table
tableelement.append(headertr);
for(var i=0; i< data.links.id.length; i++){
tableelement.append(createRow(data.links.id[i]));
}
}
function createRow(rowObject){
var trElement = "<tr>";
//used to create combo box 1 based row 1 value
var combo1 = createCombo1(rowObject,function(response){
//used to create combo box 2 based row 1 value
var combo2 = createCombo2(rowObject,function(result){
trElement+= "<td><input type='text' name='col1name' value='"+rowObject.Number+"' onblur='handleInput(this)'/></td>";
trElement+="<td><input type='text' name='col3name' value='"+rowObject.name+"'/></td>";
trElement+="<td><input type='text' name='col3name' value='"+rowObject.quantity+"'/></td>";
trElement+="<td>"+response+"</td>";
trElement+="<td>"+result+"</td>";
trElement+="<td><button>Del</button></td>";
trElement+="<td><button>Add</button></td></tr>";
});
});
return trElement;
}
function createCombo1(rowObject,callback){
var comboList = [];
//call ajax to get combo value
$.ajax({
url:"combo1data.json",
type: "GET",
dataType : "json"
})
.done(function(data, textStatus, jqXHR){
comboList = data.links.id;
var cmb1 = "<select name='cmb1' onchange='handlecmb1Change(this)'>";
for(var i=0;i < comboList.length; i++){
cmb1 +="<option value='"+comboList.id+"'>"+comboList.val+"</option>";
}
cmb1 += "</select>";
return callback(cmb1);
});
}
function createCombo2(rowObject,callback){
var comboList = [];
//call ajax to get combo value
$.ajax({
url:"combo2data.json",
type: "GET",
dataType : "json"
})
.done(function(data, textStatus, jqXHR){
comboList = data.links.id;
var cmb2 = "<select name='cmb1' onchange='handlecmb1Change(this)'>";
for(var i=0;i < comboList.length; i++){
cmb1 +="<option value='"+comboList.id+"'>"+comboList.val+"</option>";
}
cmb2 += "</select>";
return callback(cmb2);
});
}
thanks
There are several problems that need to be addressed.
First, the return value from an ajax callback won't go anywhere.
This line
var combo1 = createCombo1(rowObject);
Will set combo1 to undefined every single time. Because createCombo1() doesn't return anything. The anonymous function inside of createCombo1() is what returns the value your looking for, but in this case you can't use that return value.
What I recommend for createCombo1() and createCombo2() is to save the return value to a global variable or maybe even an array, so you can access them when they are done.
Which brings me to the next problem...how do you know when they are done?
jQuery has something called a deferred object. Which allows you to chain multiple callbacks to one function. There is a similar SO question that addresses how to use this using When().
Here is the question
There is still a lot to do on your end, but hopefully this will point you in the right direction.

Categories