How to save table content permanently - javascript

I am an absolute beginner in javascript. I tried to make an table which can save the content i type in it. I just got the total opposite from what i wanted the table deletes the content everytime i refresh the website.
Basically my question is what i have to change so i can save the data permantly and it dont vanish everytime i refresh the webpage. Also it would nice to know what i did wrong. I already tried to change some things but it got just worse
Here is some example code for you:
JS:
$(document).ready(function () {
var counter = 0;
$("#addrow").on("click", function () {
var newRow = $("<tr>");
var cols = "";
cols += '<td><input type="text" class="form-control" name="name' + counter + '"/></td>';
cols += '<td><input type="text" class="form-control" name="mail' + counter + '"/></td>';
cols += '<td><input type="text" class="form-control" name="phone' + counter + '"/></td>';
cols += '<td><input type="button" class="ibtnDel btn btn-md btn-danger " value="Delete"></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
counter++;
});
$("table.order-list").on("click", ".ibtnDel", function (event) {
$(this).closest("tr").remove();
counter -= 1
});
});
function calculateRow(row) {
var price = +row.find('input[name^="price"]').val();
}
function calculateGrandTotal() {
var grandTotal = 0;
$("table.order-list").find('input[name^="price"]').each(function () {
grandTotal += +$(this).val();
});
$("#grandtotal").text(grandTotal.toFixed(2));
}
Basic HTML:
<div class="container">
<table id="myTable" class=" table order-list">
<thead>
<tr>
<td>name</td>
<td>mail</td>
<td>phone</td>
</tr>
</thead>
<tbody>
<tr>
<td class="col-sm-4">
<input type="text" name="name" class="form-control" />
</td>
<td class="col-sm-4">
<input type="mail" name="mail" class="form-control"/>
</td>
<td class="col-sm-3">
<input type="text" name="phone" class="form-control"/>
</td>
<td class="col-sm-2"><a class="deleteRow"></a>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: left;">
<input type="button" class="btn btn-lg btn-block " id="addrow" value="Add Row" />
</td>
</tr>
<tr>
</tr>
</tfoot>

You can use the localStorage object, which stores data with no expiration date. This data will not be deleted when you refresh the page or even close the browser.
In order to do that, you first need to create the function which will save the data into localStorage.
function save_data(){
let table_data = []
$('.form-control').each(function() { table_data.push( $(this).val() )});
localStorage.setItem('table_data', JSON.stringify(table_data));
}
This function iterates through all table cells and saves its content into table_data array.
Then table_data array is converted into String with JSON.stringify and saved in localStorage.
This function should be executed every time you add, remove or edit one of the rows.
In order to do that we need to create new event handlers:
$('tbody').on("DOMSubtreeModified", function() {save_data()});
$('tbody').on('change', '.form-control', function() {save_data()});
The first one triggers save_data function every time a row is created or removed.
The second one saves data whenever the table's content is modified.
We also need a function for loading data from localStorage:
function load_data(){
let table_data = JSON.parse(localStorage.getItem('table_data'));
for (i = 1; i < table_data.length/3; i++) $("#addrow").click()
$('.form-control').each(function(index) {$(this).val(table_data[index])});
}
This function loads data from localStorage using getItem function.
The loaded data is a String, so it is converted into the array using JSON.parse.
Next, new rows are inserted according to the size of table_data array.
In the end, it iterates through all table cells and fills them with loaded data.
This function should be executed only after you the page is loaded and only if data exists in localStorage.The best way is to put this line at the bottom of ready function:
if (localStorage.getItem("table_data") != null) load_data()

Related

Dynamically add row with jQuery

I have an application that integrated with barcode scanner, like this:
I have made a row dynamically with this snippet of code:
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<div class="container" align="top" style="margin-top: 0px;">
<h1 align="center">
Barcode: <br><input type="text" id="myHeader" value="5555">
</h1>
<table id="myTable" class=" table order-list">
<thead>
<tr>
<td>Barcode</td>
<td>Item</td>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="7" style="text-align: left;">
<div align="right">
<p style="color: black;margin-right: 90px;">9.999.999</p>
</div>
<input type="button" class="btn btn-lg btn-block " id="addrow" value="Add Row" style="border-color: black;" />
</td>
</tr>
<tr>
</tr>
</tfoot>
</table>
</div>
and here is the code that I wrapped with script tag:
<script >
$(document).ready(function() {
var counter = 0;
$("#addrow").on("click", function() {
var newRow = $("<tr>");
var cols = "";
cols += '<td><input type="text" disabled value="123123123" class="form-control" name="name' + counter + '"/></td>';
cols += '<td><input type="text" disabled value="Sekop" class="form-control" name="mail' + counter + '"/></td>';
cols += '<td><input type="button" class="ibtnDel btn btn-md btn-danger " value="Delete"></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
counter++;
});
$("table.order-list").on("click", ".ibtnDel", function(event) {
$(this).closest("tr").remove();
counter -= 1
});
});
function calculateRow(row) {
var price = +row.find('input[name^="price"]').val();
}
function calculateGrandTotal() {
var grandTotal = 0;
$("table.order-list").find('input[name^="price"]').each(function() {
grandTotal += +$(this).val();
});
$("#grandtotal").text(grandTotal.toFixed(2));
} </script>
But the code above just add the row only when I clicked the Add Row button.
What I want for now is, when I scan a barcode with a barcode scanner, the row automatically added follow the scanned barcode result.
In this case it will be: "When the value on barcode on the header changed ( <h1 align="center">Barcode: 123123123</h1> , the result is same when I clicked the Add Row button.
So, please refer any approach, tutorial or example code how to do that, it would be very appreciated :)
For additional information: The purpose of this app is for cashier app on a store, like when the cashier scan a product, the result automatically appear on the app. And I developing it using Python Flask.
You have to listen to the changes made in the element. You can try with MutationObserver
$(document).ready(function() {
var counter = 0;
$("#addrow").on("click", function() {
var newRow = $("<tr>");
var cols = "";
cols += '<td><input type="text" disabled value="123123123" class="form-control" name="name' + counter + '"/></td>';
cols += '<td><input type="text" disabled value="Sekop" class="form-control" name="mail' + counter + '"/></td>';
cols += '<td><input type="button" class="ibtnDel btn btn-md btn-danger " value="Delete"></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
counter++;
});
$("table.order-list").on("click", ".ibtnDel", function(event) {
$(this).closest("tr").remove();
counter -= 1
});
});
function calculateRow(row) {
var price = +row.find('input[name^="price"]').val();
}
function calculateGrandTotal() {
var grandTotal = 0;
$("table.order-list").find('input[name^="price"]').each(function() {
grandTotal += +$(this).val();
});
$("#grandtotal").text(grandTotal.toFixed(2));
}
// Listen to the changes in the header element and add row
var target = document.querySelector('#myHeader');
setTimeout(function() {
target.textContent = "New Barcode: XXXXXXXXX"; // change text after 2 seconds
}, 2000)
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
$("#addrow").trigger("click"); // trigger the click event to add row if the header text is changed
});
});
var config = {
attributes: true,
childList: true,
characterData: true
};
observer.observe(target, config);
// otherwise
observer.disconnect();
observer.observe(target, config);
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<div class="container" align="top" style="margin-top: 0px;">
<h1 align="center" id="myHeader">Barcode: 123123123</h1>
<table id="myTable" class=" table order-list">
<thead>
<tr>
<td>Barcode</td>
<td>Item</td>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="7" style="text-align: left;">
<div align="right">
<p style="color: black;margin-right: 90px;">9.999.999</p>
</div>
<input type="button" class="btn btn-lg btn-block " id="addrow" value="Add Row" style="border-color: black;" />
</td>
</tr>
<tr>
</tr>
</tfoot>
</table>
</div>
Update: The updated question indicates that you can trigger the click event on blur event of the barcode input element:
$(document).ready(function() {
var counter = 0;
$("#addrow").on("click", function() {
var newRow = $("<tr>");
var cols = "";
var barcode = $("#myHeader").val().trim();// take the current barcode value
cols += '<td><input type="text" disabled value= '+ barcode +' class="form-control" name="name' + counter + '"/></td>';
cols += '<td><input type="text" disabled value="Sekop" class="form-control" name="mail' + counter + '"/></td>';
cols += '<td><input type="button" class="ibtnDel btn btn-md btn-danger " value="Delete"></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
counter++;
});
$("table.order-list").on("click", ".ibtnDel", function(event) {
$(this).closest("tr").remove();
counter -= 1
});
});
function calculateRow(row) {
var price = +row.find('input[name^="price"]').val();
}
function calculateGrandTotal() {
var grandTotal = 0;
$("table.order-list").find('input[name^="price"]').each(function() {
grandTotal += +$(this).val();
});
$("#grandtotal").text(grandTotal.toFixed(2));
}
// Add new row by triggering the click event on focus out
var target = document.querySelector('#myHeader');
target.addEventListener('blur', function(){
$("#addrow").trigger("click");
});
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<div class="container" align="top" style="margin-top: 0px;">
Barcode: <br><input type="text" id="myHeader" value="5555">
<table id="myTable" class=" table order-list">
<thead>
<tr>
<td>Barcode</td>
<td>Item</td>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="7" style="text-align: left;">
<div align="right">
<p style="color: black;margin-right: 90px;">9.999.999</p>
</div>
<input type="button" class="btn btn-lg btn-block " id="addrow" value="Add Row" style="border-color: black;" />
</td>
</tr>
<tr>
</tr>
</tfoot>
</table>
</div>
$('#myTable tbody').append(newRow)
I think you have problem with your jQuery selector.
Try the code shown above - hope it works for you.

Calculate total of each added row separately and total of all rows in Javascript

I am new in javascript and facing a problem. I have invoice rows which can be added by pressing on a button. Now i want to calculate the total amount for each row separately(for which the formula is (quantity * price). And the total of all rows combined should become the total of the invoice. The problem is that when I enter the price and quantity in first row, it calculates the total but when I add a new row, it does not calculate the total for new added row after entering the value. Kindly help me in this regard.
function myFunction() {
var x = document.getElementById("price").value;
var y = document.getElementById("quantity").value;
if (x != "") {
document.getElementById("total").value = x * y;
}
}
function add_fields() {
var tableid = document.getElementById('product_table');
var row = document.createElement("tr");
row.innerHTML =
'<td><input type="text" name="price" id="price" oninput="myFunction()"> </td>' +
'<td><input type="text" name="quantity" id="quantity" oninput = "myFunction()" > < /td>' +
'<td><input type="text" name="total" id="total" readonly></td>';
tableid.appendChild(row);
}
table,
tr,
td,
th {
border: 1px black solid;
}
<table>
<thead>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</thead>
<tbody id="product_table">
<tr>
<td><input type="text" name="price" id="price" oninput="myFunction();"></td>
<td><input type="text" name="quantity" id="quantity" oninput="myFunction();"></td>
<td><input type="text" name="total" id="total" readonly></td>
</tr>
</tbody>
<input type="button" name="submit" value="Add Row" onclick="add_fields();">
Use event delegation instead - add a single listener to the container, listen for input events. Then, from the target property of the event, you can get the changed input element. Use .closest to get to the parent <tr>, and then from its descendants, you can get to the associated price, quantity, and total <input>s, and assign values appropriately.
Note that this adds the handler using Javascript, rather than with inline HTML attributes, which are generally considered to be pretty poor practice and can be difficult to manage. Also, duplicate IDs in a single document is invalid HTML - IDs aren't needed anyway here, because the inputs you want are always in a predictable order inside each <tr>. So, you can remove the id and the onclick attributes from the HTML and from the row.innerHTML string:
const table = document.getElementById('product_table');
table.addEventListener('input', ({ target }) => {
const tr = target.closest('tr');
const [price, quantity, total] = tr.querySelectorAll('input');
total.value = price.value * quantity.value;
});
function add_fields() {
var row = document.createElement("tr");
row.innerHTML =
'<td><input type="text" name="price"> </td > ' +
'<td><input type="text" name="quantity"> </td>' +
'<td><input type="text" name="total" readonly></td>';
table.appendChild(row);
}
table,
tr,
td,
th {
border: 1px black solid;
}
<table>
<thead>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</thead>
<tbody id="product_table">
<tr>
<td><input type="text" name="price"></td>
<td><input type="text" name="quantity"></td>
<td><input type="text" name="total" readonly></td>
</tr>
</tbody>
<input type="button" name="submit" value="Add Row" onclick="add_fields();">

How to set name value of dynamic adding input ? javascript jquery

I have a web page for applying. In this web page, rows are dynamic add after addp button clicked.I can add new row successfully with addPf() method. And these input name attribute should be enName0, enName1, enName2....., but it works fail with name="enName"+aDWI.
Here is my html code:
<div>
<table>
<tr>
<td>
<input type="button" id="addP" onclick="addPf()" value="addPeople">
</td>
</tr>
<tr>
<td>
new row added in here;
</td>
</tr>
</table>
</div>
Here is my javascript code:
<script>
var aDWI=0;
function addPf()
{
newrow = '<tr><td><input style="width:98%" name="enName"+aDWI></td></tr>';
$(newrow).insertAfter($('#staTable tr:eq('+aDWI+')'));
aDWI = aDWI + 1;
}
</script>
name="enName"+aDWI is not right.I have no idea about this, who can help me ?
Change from
newrow = '<tr><td><input style="width:98%" name="enName"+aDWI></td></tr>';
to
newrow = '<tr><td><input style="width:98%" name="enName'+aDWI+'"></td></tr>';
The issue is because you need to concatenate the variable in the string correctly, using the ' character.
Also note that you should really be using unobtrusive event handlers instead of the outdated on* event attributes. In addition, you can simplify the logic by using jQuery's append(), like this:
var aDWI = 0;
$('#addP').click(function() {
newrow = '<tr><td><input style="width:98%" name="enName' + aDWI + '" value="' + aDWI + '"></td></tr>';
$('#staTable').append(newrow);
aDWI = aDWI + 1;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<table id="staTable">
<tr>
<td>
<input type="button" id="addP" value="addPeople">
</td>
</tr>
<tr>
<td>
new row added in here;
</td>
</tr>
</table>
</div>
Just update it with
<script>
var aDWI=0;
function addPf()
{
newrow = '<tr><td><input style="width:98%" name="enName'+aDWI+'"></td></tr>';
$(newrow).insertAfter($('#staTable tr:eq('+aDWI+')'));
aDWI = aDWI + 1;
}
</script>

Pass HTML Element Values Created On Client Side Via JS To Server Side (ASP.Net)

I'm using ASP.NET with Bootstrap to create a website.
Inside the .APSX HTML File I have a JavaScript function that adds additional Rows to the HTML Table containing TextAreas.
Now the problem is - How do I process TextArea data from newly created Rows on the server side?
As I've researched - whatever is created on Client Side dynamically via JavaScript cannot be "seen" on the server side.
Furthermore, all the additionally added rows are lost on asp:button Click event.
I've read that you can somehow pass JS data to Server side using JSON, but I'm not familiar with either of them (the JS code I'm using was found on the Internet).
<table id="myTable" class="table" style="width:100%;">
<tbody>
<tr>
<td style="width:90%;">
<textarea rows="2" name="name" style="width:100%;" runat="server"></textarea>
</td>
<td style="width:10%;"> <a class="deleteRow" style="width:100%;"></a>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: left;">
<input type="button" id="addrow" value="Add Row" runat="server" />
</td>
</tr>
</tfoot>
</table>
<script>
$(document).ready(function() {
var counter = 0;
$("#addrow").on("click", function() {
counter = $('#myTable tr').length - 2;
var newRow = $("<tr>");
var cols = "";
cols += '<td style="width:90%;"><textarea rows="2" name="name" style="width:100%;" runat="server"></textarea></td>';
cols += '<td style="width:10%;"><input type="button" style="width:100%;" class="ibtnDel" value="Delete"></td>';
newRow.append(cols);
if (counter == 20) $('#addrow').attr('disabled', true).prop('value', "You've reached the limit");
$("table.table").append(newRow);
counter++;
});
$("table.table").on("change", 'input[name^="price"]', function(event) {
calculateRow($(this).closest("tr"));
calculateGrandTotal();
});
$("table.table").on("click", ".ibtnDel", function(event) {
$(this).closest("tr").remove();
calculateGrandTotal();
counter -= 1
$('#addrow').attr('disabled', false).prop('value', "Add Row");
});
});
function calculateRow(row) {
var price = +row.find('input[name^="price"]').val();
}
</script>
Could I perhaps somehow Request the Table on server side and then itterate through it?
Any help or hints will be appreciated.

jquery to sum two inputs on dynamic table and display in third

With the SO community I have got a script that adds rows with unique names to a table. I want to take two inputs on each row and multiply them together and display result in a third input.
the fiddle is at http://jsfiddle.net/yUfhL/231/
My code is:
HTML
<table class="order-list">
<tr><td>Product</td><td>Price</td><td>Qty</td><td>Total</td></tr>
<tr>
<td><input type="text" name="product" /></td>
<td><input type="text" name="price" /></td>
<td><input type="text" name="qty" /></td>
<td><input type="text" name="linetotal" /></td>
</tr>
</table>
<div id="grandtotal">
Grand Total Here
</div>
JS
var counter = 1;
jQuery("table.order-list").on('change','input[name^="product"]',function(event){
event.preventDefault();
counter++;
var newRow = jQuery('<tr><td><input type="text" name="product' +
counter + '"/></td><td><input type="text" name="price' +
counter + '"/></td><td><input type="text" name="qty' +
counter + '"/></td><td><input type="text" name="total' +
counter + '"/></td><td><a class="deleteRow"> x </a></td></tr>');
jQuery('table.order-list').append(newRow);
});
jQuery("table.order-list").on('click','.deleteRow',function(event){
$(this).closest('tr').remove();
});
$('table.order-list tr').each(function() {
var price = parseInt( $('input[id^=price]', this).val(), 10 );
var qty = parseInt( $('input[id^=qty]' , this).val(), 10 );
$('input[id^=linetotal]', this).val(price * qty);
});
So currently I cant get the js to fire that gets the product of the two cells, qty and price. I want to display result in linetotal.
The last part of this would be to display the sum of all linetotals as a grand total in the div grandtotal
Help appreciated as always.
You're only giving the elements a name attribute, but using the id selector ([id^=price]). It's much easier to give them a specific class than having to use that "id starts with" selector. Also, when do you want the line totals to be calculated? And when do you want the grand total to be calculated? On what event(s)?
Here's my interpretation of how it should look:
<table class="order-list">
<thead>
<tr><td>Product</td><td>Price</td><td>Qty</td><td>Total</td></tr>
</thead>
<tbody>
<tr>
<td><input type="text" name="product" /></td>
<td>$<input type="text" name="price" /></td>
<td><input type="text" name="qty" /></td>
<td>$<input type="text" name="linetotal" readonly="readonly" /></td>
<td><a class="deleteRow"> x </a></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: center;">
<input type="button" id="addrow" value="Add Product" />
</td>
</tr>
<tr>
<td colspan="5">
Grand Total: $<span id="grandtotal"></span>
</td>
</tr>
</tfoot>
</table>
And the JS:
$(document).ready(function () {
var counter = 1;
$("#addrow").on("click", function () {
counter++;
var newRow = $("<tr>");
var cols = "";
cols += '<td><input type="text" name="product' + counter + '"/></td>';
cols += '<td>$<input type="text" name="price' + counter + '"/></td>';
cols += '<td><input type="text" name="qty' + counter + '"/></td>';
cols += '<td>$<input type="text" name="linetotal' + counter + '" readonly="readonly"/></td>';
cols += '<td><a class="deleteRow"> x </a></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
});
$("table.order-list").on("change", 'input[name^="price"], input[name^="qty"]', function (event) {
calculateRow($(this).closest("tr"));
calculateGrandTotal();
});
$("table.order-list").on("click", "a.deleteRow", function (event) {
$(this).closest("tr").remove();
calculateGrandTotal();
});
});
function calculateRow(row) {
var price = +row.find('input[name^="price"]').val();
var qty = +row.find('input[name^="qty"]').val();
row.find('input[name^="linetotal"]').val((price * qty).toFixed(2));
}
function calculateGrandTotal() {
var grandTotal = 0;
$("table.order-list").find('input[name^="linetotal"]').each(function () {
grandTotal += +$(this).val();
});
$("#grandtotal").text(grandTotal.toFixed(2));
}
http://jsfiddle.net/QAa35/
In your JS, you weren't using linetotal for the one dynamic input's name. There were other several minor modifications I made. You might as well use <thead>, <tbody> and <tfoot> since you do have those sections in the <table>. Also, I don't think it's a good design to have a new row automatically added when the "product" inputs are changed. That can happen often, and their intent may not be to add a new product...a button is much more friendly. For example, say you type in "asdf" to the first "product" input, then click somewhere. A new row is added. Say you made a typo so you go back and change it to "asd", then click somewhere. Another new row is added. That doesn't seem right.
This function should do the trick:
function updateGrandTotal() {
var prices = [];
$('input[name^="price"]').each(function () {
prices.push($(this).val());
});
var qnts = [];
$('input[name^="qty"]').each(function () {
qnts.push($(this).val());
});
var total = 0;
for(var i = 0; i < prices.length; i++){
total += prices[i] * qnts[i];
}
$('#grandtotal').text(total.toFixed(2));
}
You just need to bind it to the table change event to update the grand total every time an input changes:
$("table.order-list").change(updateGrandTotal);
Here is a working fiddle.

Categories