Issues with appending Item to container - javascript

I am trying to append a new item and price (two input fields) to a container. I tried adding a class to the parent element and than adding both items at the same time.
For some reason I am not able to make this work.
'use strict';
$(document).ready(init);
function init(){
// $('#groupOne').on('click', '.item', clickHolder);
// $('#groupOne').on('click', '.item', clickCup);
$('#addButton').on('click', '.addItem', addFunction);
}
function addFunction(){
var item = $('.addItem').val();
console.log(item);
var placeIt = $('<td>' + item + '</td>');
('#groupOne').appendItem;
$('.addItem').val('');
}
<input type="text" class="addItem">
<input type="number" class="addItem">
<button id="addButton">Add</button>
</div>
<table id="groupOne">
<tr>
<th>Item</th>
<th>Price</th>
</tr>
<tr class="item">
<td>Banana</td>
<td>14.99</td>
</tr>
<tr class="item">
<td>Apple</td>
<td>5.99</td>
</tr>
<tr class="item">
<td>Tomato</td>
<td>8.99</td>
</tr>
</table>

You have some errors. First I'm not sure why you are using event delegation. Then you retrieve only the price of the item. Also you are using appendItem which is not javascript method as far as I know(I used jquery .append() method on my snippet because you have jquery object but you can use javascript appendChild on javascript object). I create the following snippet:
'use strict';
$(document).ready(init);
function init() {
//no need to use event delegation here. click event listener is enough
$('#addButton').on('click', addFunction);
}
function addFunction() {
//get item name
var itemName = $('.addItem:eq(0)').val();
//get item price
var itemPrice = $('.addItem:eq(1)').val();
//create jquery object
var placeIt = $('<tr><td>' + itemName + '</td><td>' + itemPrice + '</td></tr>');
//append it
$('#groupOne').append(placeIt);
$('.addItem').val('');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="addItem" />
<input type="number" class="addItem" />
<button id="addButton">Add</button>
<table id="groupOne">
<tr>
<th>Item</th>
<th>Price</th>
</tr>
<tr class="item">
<td>Banana</td>
<td>14.99</td>
</tr>
<tr class="item">
<td>Apple</td>
<td>5.99</td>
</tr>
<tr class="item">
<td>Tomato</td>
<td>8.99</td>
</tr>
</table>

Related

take an id of a forEach method and pass it to asp-route-id

This is my View :
<a class="mybut btn btn-info" id="check" asp-page-handler="Delete" asp-route-id="" onclick="takeId()"> Delete Person</a>
<table id="datatable" class="table">
<thead>
<tr>
<th>select</th>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
#foreach (var item in #Model.MyViewModels)
{
<tr>
<td><input type="checkbox" id="box" value="#item.Id" /></td>
<td>#item.Id</td>
<td>#item.FullName</td>
</tr>
}
</tbody>
</table>
and this is my Index Model:
public void OnGetDelete(long id)
{
_customerApplication.Delete(id);
}
and my js codes:
function takeId() {
var id = $("#box").attr('value');
$("#check").attr('asp-route-id',id);
}
when i click on each item, i need to take the item's Id, and pass it to asp-route-id in "a" tag ,it seems that there are some wrongs in my codes, because when i select each item and click on "a" tag, The id returns the value 0
here is a demo to allow only one checkbox checked,and when one checkbox is checked,the id of anchor tag will be changed:
<a class="mybut btn btn-info" id="check" asp-page-handler="Delete" asp-route-id="0"> Delete Person</a>
<table id="datatable" class="table">
<thead>
<tr>
<th>select</th>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
#foreach (var item in #Model.MyViewModels)
{
<tr>
<td><input type="checkbox" name="box" value="#item.Id" /></td>
<td>#item.Id</td>
<td>#item.FullName</td>
</tr>
}
</tbody>
</table>
js:
$('input[name=box]').change(function(){
$('input:checkbox').not(this).prop('checked', false);
var id=$('input[name=box]:checked').val();
var id1 = id == undefined ? 0 : id;
var href = $("#check").attr('href').split("?");
var href1 = href[0] + "?id=" + id1 + "&" + href[1].split("&")[1];
$("#check").attr('href',href1);
})
result:
The asp-route-id attribute is parsed by the anchor tag helper. Tag helpers are executed server-side to create html output that is sent to the browser. The asp- attributes are not included in the output because they have no meaning for the browser.
For example if you have this in your .cshtml file:
<a asp-page-handler="Delete" asp-route-id="1">Delete Person</a>
The anchor tag helper will parse the asp- attributes and generate the following html output:
Delete Person
The generated element is added to the html response that is sent to the browser. Now that the element is rendered in the browser (client-side), adding the asp- attribute with JavaScript will not have any effect.
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro?view=aspnetcore-6.0
Here's what you could try:
function takeId() {
var id = $('#box').attr('value');
var href = $('#check').attr('href') + '&id=' + id;
$("#check").attr('href', href);
}

Change style for element from ng-repeat

I am trying to uniqeley identify buttons in a tablerow, so I can change the style if one of them is clicked. Here is the table i am working on:
And here is the code:
<table class="table">
<thead>
<tr>
<th>Allergi navn</th>
<th>Allergi verdi</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="items in $ctrl.allergen">
<td>
<b>
{{items.Allergennavn}}
</b>
</td>
<td id="{{$index}}">
<button
id="tableButton"
type="button"
class="btn-grey"
ng-repeat="item in $ctrl.allergenVerdiType"
ng-click="$ctrl.allergiAssigned($index, items, item)"
>
<b>
{{item.Allergenverdi}}
</b>
</button>
<hr>
</td>
</tr>
</tbody>
</table>
And js:
ctrl.allergiAssigned = function($index, itemAllergen, itemAllergenType){
var index = $('button').index(this);
$(index, '#tableButton').css("background-color", "green");
}
I have tried several approaches to reference the specific button-element, using this, index, etc. I also need to verfiy that for every row, there is only one of the buttons that are selected.
I also tried to pass {{$index}} to get a unique identifier for the row, but jquery doesn't support the syntax.
UPDATE based on answers:
<table class="table">
<thead>
<tr>
<th>Allergi navn</th>
<th>Allergi verdi</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="items in $ctrl.allergen">
<td>
<b>
{{items.Allergennavn}}
</b>
</td>
<td id="{{$index}}">
<button id="tableButton" type="button"
class="btn-grey" ng-class="{activeBtn: item.active == true}"
ng-repeat="item in $ctrl.allergenVerdiType"
ng-click="$ctrl.select(items.type, item)">
{{item.AllergenverditypeKode}}</button>
<hr>
</td>
</tr>
</tbody>
</table>
ctrl.select = function(items, index) {
angular.forEach(items, function(item){
item.active=false;
});
index.active = true;
};
index returns undefined
You can change the CSS class based on the user action by using ng-class directive.
details
Code will be like that.
In CSS class :.activeButton:{background-color", "green"}
In button ng-click function : buttonClicked[$index]=true;
In Html button input:
..... ng-class="{'btn-grey':'btn-grey',
'activeButton':<add your condition like 'buttonClicked[$index]'>}"
To uniquely identify an element in nested ng-repeat, you can assign a unique Id to it by combining the $index from the parent loop and from the child loop as :
id="tableButton_{{$parent.$index}}_{{$index}}"
Now, pass the parent index and the child index to the event, fetch the element and change its css:
ng-click="assigned($parent.$index, $index)"
Below is a snippet of a sample data:
angular.module("app", []).controller("ctrl", function($scope) {
$scope.items = ["Item A", "Item B"];
$scope.buttonTypes = ["Btn1", "Btn2", "Btn3", "Btn4"];
$scope.assigned = function(parentIndex, childIndex) {
//Reset all buttons for one row
var parentBtns = "#" + parentIndex + " :button";
$(parentBtns).css("background", "transparent");
//Change the selected button css
var btn = "#tableButton_" + parentIndex + "_" + childIndex;
$(btn).css("background", "green");
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="app" ng-controller="ctrl">
<table class="table">
<thead>
<tr>
<th>Allergi navn</th>
<th>Allergi verdi</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items">
<td>
<b>{{item}}</b>
</td>
<td id="{{$index}}">
<button id="tableButton_{{$parent.$index}}_{{$index}}" type="button" class="btn-grey" ng-repeat="type in buttonTypes" ng-click="assigned($parent.$index, $index)">
<b>{{type}}</b>
</button>
<hr>
</td>
</tr>
</tbody>
</table>
</body>
You can try something like the below code, also you check you given working plunker example.
Template:
<button id="tableButton" type="button" class="defaultBtn" ng-class="{activeBtn: item.active}" ng-repeat="item in items.type" ng-click="select(items.type, item)">{{item.value}}</button>
Controller:
$scope.select= function(items, index) {
// You can remove this loop part if you don't want to reset your selection..
angular.forEach(items, function(item){
item.active=false;
});
index.active = true;
};

How to sum values from table column and update when remove/add new row

I'm trying to sum the values of one specific column but honestly I dont know how to it, also I want to refresh that total value when I add or remove some row, what can I do to make this? I'm triying with the anwsers of similar question here on SO but they sum values from all columns and I only want to do that for an specific column! Here is what I have:
function deleteRow(btn) {
var row = btn.parentNode.parentNode;
row.parentNode.removeChild(row);
}
$('#xd').click(function() {
var lines = "";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td>1</td>';
lines += '<td>100.00</td>';
lines += '<td><input type="button" value="Delete" onclick="deleteRow(this)"/></td>';
$('#TableBody').append(lines);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td>10</td>
<td>12.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td>5</td>
<td>10.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td>15</td>
<td>170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
In the above code I added the Total columns (Price, Quantity) manually, I want to update total result when user add/remove a row.
Your approach is a bit brittle for long term use, but as a proof of concept this may help.
The key technique for summing up an array of numbers is to use Array.reduce, which works like this:
var array = [1, 2, 6, 1, 5];
var total = array.reduce(function(total, number) {
return total + number;
}, 0);
document.write('<h1>Total: <code>' + total + '</code></h1>');
Given an array of numbers, iterate over each of them and add number to total, with total starting at 0.
Array.reduce takes two arguments: a function to execute over each item, and a starting value. The iterator function will receive two arguments, in your case the running total and the next number.
See the MDN documentation on Array.reduce for more details.
Some Tips
Break things down into smaller functions whenever possible.
Limit use of global variables, but when you do need them, be clean and consistent about it
Limit storing data on the DOM (I'm violating this slightly, but this is just sketch code)
Try and write code in a way that's reusable
The benefits of this approach are it makes it a bit easier to add new features/change what you built. For example, if we write a generic function getColumnTotal(selector), which would let you specify a jQuery selector for a column's cells (ex: .priceCell), then you can reuse that for other columns like quantity.
I assume you were working towards a grand total cell, that displays the total of all individual orders/rows. To do that, all we'd need to do is calculate the subtotal for each row, add a new column for that, then re-use that getColumnTotal function to sum up all the sub-totals. Voila, grand total.
Note that my code doesn't account for errors, so you may need to handle situations where invalid quantity or price data is input.
var $tableBody = $('#TableBody');
var $totalQuantityCell = $('#totalQuantityCell');
var $totalPriceCell = $('#totalPriceCell');
var $totalGrandCell = $('#grandTotalCell');
// Add a row with random values on "Add Row" button click
$('#xd').click(addRandomRow);
function addRandomRow(event) {
var randomCode = Math.round(Math.random() * 4);
var randomClient = Math.round(Math.random() * 15);
var randomCharge = ( Math.round(Math.random()) ? 'Debit' : 'Credit' );
var randomQuantity = Math.ceil(Math.random() * 5);
var randomPrice = Math.ceil(Math.random() * 100).toFixed(2);
addRow(randomCode, randomClient, randomCharge, randomQuantity, randomPrice);
};
// Add some rows to start
addRandomRow();
addRandomRow();
// Listen for clicks on ".deleteRowButton" within the table
$tableBody.on('click', '.deleteRowButton', function(event) {
deleteRow( $(event.target).data('row') );
updateTotals();
});
// --------------------------
function addRow(code, client, chargeType, quantity, price) {
// Create a new row element
var idNum = ( $tableBody.find('tr').length + 1 );
var rowId = 'row-' + idNum;
var $row = $('<tr id="' + rowId + '"></tr>');
// Add the table cells
$row.append('<td class="idCell">' + idNum + '</td>');
$row.append('<td class="codeCell">' + code + '</td>');
$row.append('<td class="clientCell">' + client + '</td>');
$row.append('<td class="chargeTypeCell">' + chargeType + '</td>');
$row.append('<td class="quantityCell">' + quantity + '</td>');
$row.append('<td class="priceCell">' + price + '</td>');
$row.append('<td class="orderTotalCell">' + getSubtotal(quantity, price) + '</td>');
$row.append('<td><input type="button" value="Delete" class="deleteRowButton" data-row="#' + rowId + '" /></td>');
// Append the row to the table body
$tableBody.append($row);
updateTotals();
}
function deleteRow(rowId) {
$(rowId).remove();
}
function updateTotals() {
var totalQuantity = getColumnTotal('.quantityCell');
var totalPrice = getColumnTotal('.priceCell');
var totalOrder = getColumnTotal('.orderTotalCell');
$totalQuantityCell.text( totalQuantity );
$totalPriceCell.text( toMoney(totalPrice) );
$totalGrandCell.text( toMoney(totalOrder) );
}
/**
A standard function to calaculate the subtotal of a row, this is
where you could apply tax or other data transformations if need be.
*/
function getSubtotal(quantity, price) {
return (quantity * price).toFixed(2);
}
/**
Takes a jQuery selector, finds all matching elements for it, and totals up their contents.
It works by converting the elements list to an Array and then using Array.reduce.
#see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
*/
function getColumnTotal(selector) {
return Array.from( $(selector) ).reduce(sumReducer, 0);
}
/**
The reducer function that adds up a running total. This function parses the innerHTML content
of an element and converts it to a number so math works on it.
*/
function sumReducer(total, cell) {
return total += parseInt(cell.innerHTML, 10);
}
function toMoney(number) {
return '$' + number.toFixed(2);
}
#TableHead td {
border-bottom: 1px #000 solid;
}
.orderTotalCell,
#grandTotalCell,
#totalPriceCell {
text-align: right;
}
#TableFooter tr:first-child td {
border-top: 1px #000 solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead id="TableHead">
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Order Total</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Sub-Total</td>
<td id="totalQuantityCell">–</td>
<td id="totalPriceCell">–</td>
<td id="grandTotalCell">–</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
wow lots of answers but here is a somewhat of a more object oriented approach.
function row(Id, Code, Client, DebitCredit, Quantity, Price) {
this.Id = Id;
this.Code = Code;
this.Client = Client;
this.DebitCredit = DebitCredit;
this.Quantity = Quantity;
this.Price = Price;
}
function model() {
this.rows = [];
}
var mymodel = new model();
$(document).ready(function() {
mymodel.rows.push(new row(1, 1, 3, 'Debit', 10, 12))
mymodel.rows.push(new row(2, 2, 12, 'Debit', 5, 10))
draw();
$("body").on("click", ".delete", function() {
var id = $(this).data('id');
for (i = 0; i < mymodel.rows.length; i++) {
console.log(mymodel.rows[i].Id);
if (mymodel.rows[i].Id == id) {
mymodel.rows.splice(i, 1);
}
}
draw();
});
$('#add').click(function() {
mymodel.rows.push(new row(
$('#Id').val(),
$('#Code').val(),
$('#Client').val(),
'Debit',
Number($('#Quantity').val()),
Number($('#Price').val())
))
draw();
});
})
function draw() {
$('tbody').empty();
var totalQuantity = 0;
var totalPrice = 0;
$.each(mymodel.rows, function(i, row) {
totalQuantity += row.Quantity;
totalPrice += row.Price;
var myrow = '<tr>'
$.each(row, function(key, value) {
myrow += '<td>' + value + '</td>'
});
myrow += '<td><input type="button" class="btn btn-danger delete" data-id="' + row.Id + '" value="X"/></td>'
myrow += '<tr>'
$('tbody').append(myrow);
});
$('#totalQuantity').text(totalQuantity)
$('#totalPrice').text(totalPrice)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<table class="table table-condensed">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Delete</td>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan=7>Total Quantity:
<span id="totalQuantity"></span> Total Price:
<span id="totalPrice"></span>
</td>
</tr>
</tfoot>
</table>
<form class="form-inline">
<div class="form-group">
<label for="id">Id:</label>
<input type="number" class="form-control" id="Id">
</div>
<div class="form-group">
<label for="Code">Code:</label>
<input type="number" class="form-control" id="Code">
</div>
<div class="form-group">
<label for="Client">Client:</label>
<input type="number" class="form-control" id="Client">
</div>
<div class="form-group">
<label for="Quantity">Quantity:</label>
<input type="number" class="form-control" id="Quantity">
</div>
<div class="form-group">
<label for="Price">Price:</label>
<input type="number" class="form-control" id="Price">
</div>
<input type="button" class="btn btn-info" value="add" id="add" />
</form>
You are missing:
<tr> </tr>
Tags when you add a new row. Also, just add a class that will add up "Quantities" and "Prices". Here's a working solution. Hope it helps!
function deleteRow(btn) {
var row = btn.parentNode.parentNode;
row.parentNode.removeChild(row);
sumOfColumns();
}
function sumOfColumns(){
var totalQuantity = 0;
var totalPrice = 0;
$(".someClass").each(function(){
totalQuantity += parseInt($(this).html());
$(".someTotalClass").html(totalQuantity);
});
$(".classPrice").each(function(){
totalPrice += parseInt($(this).html());
$(".someTotalPrice").html(totalPrice);
});
}
$(document).ready(function () {
$('#xd').click(function() {
var lines = "";
lines += '<tr>';
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td class = "someClass">1</td>';
lines += '<td class = "classPrice">100.00</td>';
lines += '<td><input type="button" value="Delete" onclick="deleteRow(this)"/></td>';
lines += '</tr>';
$('#TableBody').append(lines);
sumOfColumns();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td class = "someClass">10</td>
<td class = "classPrice">12.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td class = "someClass">5</td>
<td class = "classPrice">10.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td class = "someTotalClass">15</td>
<td class = "someTotalPrice"">170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
You can create a function to calculate total and call it after you add each line and on page load if you have some initial value.
function setTotal()
{
var totalPrice=0;
var totalQty=0;
$('#TableBody').find('tr').each(
function(){
totalQty +=parseFloat($(this).find('td').eq(4).text());
totalPrice +=parseFloat($(this).find('td').eq(5).text());
//console.log(totalPrice);
});
$('#TableFooter').find('tr td').eq(1).text(totalQty);
$('#TableFooter').find('tr td').eq(2).text(totalPrice);
}
$(function(){
setTotal();
})
$('#ID').find('tr') will find all the rows of table with id 'ID'. then you iterate through each tr using each function. Then in each row you find all the td similarly and get to specific td using eq function. eq takes index of the element.
Here is running fiddler : https://jsfiddle.net/8a4umvdr/
There are several flaws within your script, which I will want to walk you through so that you can better understand the process:
Avoid using inline JS. If you want to bind events dynamically, you can use .on() instead. Since the table is present on DOM ready, you can use $('#Table').on(...) to listen to click events on the delete button
Modularise sum computation into a single function. You can create a function, say computeSum(), which will be called every time you modify the table: be it when a table row is added, or a table row is deleted. You can also call this function at runtime, so that you do not have to use server-side languages to precompute the starting sums.
In my example below, I will fetch the text node in the 5th and 6th columns (which is 4 and 5 by zero-based index), and convert them to float by appending + in front of them
I have also used the .toFixed(2) function when printing the sums, so that its nicely showing two decimal places.
Fix your HTML injection. Remember that for <td> elements to be valid, they have to be nested in <tr>. You seem to have left that out by accident.
So here is a completely functional example of your code snippet:
$(function() {
// Function to compute sum
var computeSum = function() {
// Get the total quantity and price by column index
var quantity = 0,
price = 0;
// Iterate through each row
$('#TableBody tr').each(function() {
quantity += +$(this).find('td').eq(4).text();
price += (+$(this).find('td').eq(5).text() * +$(this).find('td').eq(4).text());
});
// Update sum
$('#TableFooter td.total.quantity').text(quantity.toFixed(2));
$('#TableFooter td.total.price').text(price.toFixed(2));
};
// Use on to bind click event handlers to input buttons with delete-row action
$('#Table').on('click', 'input[type="button"][data-action="delete-row"]', function(e) {
e.preventDefault();
// Delete row
$(this).closest('tr').remove();
// Recompute sum
computeSum();
});
$('#xd').click(function() {
// Remember to wrap your cells within <tr>
var lines = "<tr>";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td>1</td>';
lines += '<td>100.00</td>';
lines += '<td><input type="button" value="Delete" data-action="delete-row" /></td>';
lines += "</tr>";
// Append new table row
$('#TableBody').append(lines);
// Recompute sum
computeSum();
});
// Compute sum when starting up
computeSum();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td>10</td>
<td>12.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td>5</td>
<td>10.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td class="total quantity">15</td>
<td class="total price">170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
Further improvements
There are some minor improvements that you can make to my code above, but they are considered non-mission critical and hence I did not include them in my original answer.
Extensibility. If you want to compute additional columns, it would be difficult to rewrite the same lines over and over again. Instead, I recommend you store the sums in an object instead.
Value fetching. We are retrieving values based on the text node in the column. Sometimes, you do not want that—say you want to include currencies, or other texts in the quantity and/or price column. In that sense, you might want to store such data in a custom HTML5 data- attribute instead.
$(function() {
// Function to compute sum
var computeSum = function() {
// Get the total quantity and price by column index
var sums = { quantity: 0, price: 0 };
// Iterate through each table cell
$('#TableBody tr').each(function() {
sums.quantity += +$(this).find('td').eq(4).data('value');
sums.price += (+$(this).find('td').eq(4).data('value')*+$(this).find('td').eq(5).data('value'));
});
// Update sum
$.each(sums, function(key, value) {
$('#TableFooter td.total.'+key).text(value.toFixed(2));
});
};
// Use on to bind click event handlers to input buttons with delete-row action
$('#Table').on('click', 'input[type="button"][data-action="delete-row"]', function(e) {
e.preventDefault();
// Delete row
$(this).closest('tr').remove();
// Recompute sum
computeSum();
});
$('#xd').click(function() {
// Remember to wrap your cells within <tr>
var lines = "<tr>";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td class="quantity" data-value="1">1</td>';
lines += '<td class="price" data-value="100.00">100.00</td>';
lines += '<td><input type="button" value="Delete" data-action="delete-row" /></td>';
lines += "</tr>";
// Append new table row
$('#TableBody').append(lines);
// Recompute sum
computeSum();
});
// Compute sum when starting up
computeSum();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td class="quantity" data-value="10">10</td>
<td class="price" data-value="12.00">12.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td class="quantity" data-value="5">5</td>
<td class="price" data-value="10.00">10.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td class="total quantity">15</td>
<td class="total price">170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">

Sortable js none-jquery plugin sorts divs but not tables

I am using this Sortable plugin by Rubaxa, with the help of which I would like to sort my nested tables with the class of "block".
HTML
<table id="table">
<tbody>
<tr class="block">
<td>
<table>
<tr>
<td>item 1</td>
</tr>
</table>
</td>
</tr>
<tr class="block">
<td>
<table>
<tr>
<td>item 2</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
<div id="div">
<div class="block">1</div>
<div class="block">2</div>
</div>
JS
var el = document.getElementById('table'),
newEl = document.getElementById('div');
new Sortable(el, {
draggable: '.block'
});
new Sortable(newEl, {
draggable: '.block'
});
But I cannot get it to work with tables.
Does this plugin allow sorting only direct children? And is it because of the structure of tables it wont work? Or is it for some other reason?
jsFiddle link
It only works for first level children:
Solution
Ad an ID to tbody
<tbody id="rows">
Use this id to apply sort.
el = document.getElementById('rows')
Working example
I too had the same question and found a great answer here.
<tbody id="sortrows">
var sort = new Sortable(sortrows, {
onSort: function (evt) {
console.log(evt.oldIndex + ' -> ' + evt.newIndex);
document.getElementById('displayText').innerHTML=evt.oldIndex + ' -> ' + evt.newIndex;
} });
Adding a Working example

Adding row to table with datepicker

I am trying to add row with button click in table(Add Row). I am trying to add 2 fields dynamically.
1) slno
2) Date/ Time.
My problems :
1) Row is not getting added.
2) How to assign datepicker to "Date /Time" field, added dynamically.
Jsfiddle is http://jsfiddle.net/RXzs7/12/
Pl help.
html code :
<script>
$(document).ready(function() {
$('.date').each(function() {
$(this).datepicker({ minDate:"-1m",maxDate:"0" });
});
});
</script>
<body>
<div id="lpage_container">
<div class="lform_container">
<h3>DETAILS OF LOCAL CONVEYANCE EXPENSES :</h3>
<form id="localexpenses" action="">
<table summary="local expense" id="localexpense_table" width="500" border="1">
<thead>
<tr>
<th width="1%" align="center"><strong>Sl.
No.</strong></th>
<th width="7%" align="center">
<strong>Date/Time</strong></th>
<th width="8%" align="center">
<strong>Remove</strong></th>
</tr>
</thead>
<tbody bgcolor="#CCCCCC">
<tr>
<td width="1%" align="center"><input type="text"
name="lsrno_00" id="srno_00" size="1" value="0"></td>
<td width="7%" align="center"><input type="text" class="date"
name="ldate_00" id="ldate_00" value="" size="8"></td>
<td> </td>
</tr>
</tbody>
</table>
<table summary="local buttons" width="500" border="1">
<tr>
<td align="right"><input type="button" value="Add Row"
id="add_ExpenseRowlocal">
</tr>
</table>
</form>
</div><!-- END subject_marks -->
<div class="clearfix"></div>
</div>
JS code :
$(function(){
// GET ID OF last row and increment it by one
var $lastChar =1, $newRow;
$get_lastID = function(){
var $id = $('#localexpense_table tr:last-child td:first-child input').attr("name");
$lastChar = parseInt($id.substr($id.length - 2), 10);
console.log('GET id: ' + $lastChar + ' | $id :'+$id);
$lastChar = $lastChar + 1;
$newRow = "<tr> \
<td><input type='text' name='lsrno_0"+$lastChar+"' value='0"+$lastChar+"' size='1'readonly /></td> \
<td><input type='text' class='date' name='ldate_0"+$lastChar+"' id='date_0"+$lastChar+"' size='8'/></td> \
<td><input type='button' value='Remove' class='del_ExpenseRowlocal' /></td> \
</tr>";
return $newRow;
};
// ***** -- START ADDING NEW ROWS
$('#add_ExpenseRowlocal').on("click", function(){
if($lastChar <= 9){
$get_lastID();
$('#localexpense_table tbody').append($newRow);
} else {
alert("Reached Maximum Rows!");
}
});
$(document).on("click", ".del_ExpenseRowlocal", function(){
$(this).closest('tr').remove();
$lastChar = $lastChar-2;
});
});
What jQuery version are you using? In your fiddle you have not added jQuery via the framework tab but under extenral resources you have two versions: 1.6.2 and 1.11.0. When I try and run it I get an error in the console that $().onis not a function. .on() came in jQuery 1.7 so if you are using 1.6.2 then you cannot use .on().
As for the date picker, when you run
$('.date').each(function() {
$(this).datepicker({ minDate:"-1m",maxDate:"0"
});
in your document ready you add a date picker to all field with class date which currently exist. You must add the date picker to the new date fields after you have added the row to the DOM. Something like
$('.date', $('#localexpense_table tbody tr').filter(':last')).each(function() {
$(this).datepicker({ minDate:"-1m",maxDate:"0" });
});
after your .append() call should work.
Working fiddle (needs some styles fixing for the added rows)

Categories

Resources