如何对表列中的值求和并在删除/添加新行时更新

时间:2017-01-15 00:30:51

标签: javascript jquery

我正在尝试总结一个特定列的值,但老实说我不知道​​怎么做,我想在添加或删除某些行时刷新该总值,我该怎么做才能做到这一点?我在这里对类似问题的问题进行了嘲讽,但他们总结了所有列的值,我只想为特定的列做这个!这就是我所拥有的:

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">

在上面的代码中,我手动添加了总列数(价格,数量),我想在用户添加/删除行时更新总结果。

5 个答案:

答案 0 :(得分:2)

很多答案,但这是一种更加面向对象的方法。

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>

答案 1 :(得分:1)

你错过了:

<tr> </tr>
添加新行时,

标记。此外,只需添加一个将添加“数量”“价格”的类。这是一个有效的解决方案。希望它有所帮助!

   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">

答案 2 :(得分:0)

您的方法对于长期使用来说有点脆弱,但作为概念证明,这可能有所帮助。

总结一组数字的关键技巧是使用Array.reduce,其工作原理如下:

&#13;
&#13;
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>');
&#13;
&#13;
&#13;

给定一组数字,迭代每个数字并将number添加到totaltotal0开始。 Array.reduce有两个参数:一个在每个项目上执行的函数和一个起始值。迭代器函数将接收两个参数,在您的情况下是运行总计和下一个数字。

有关详细信息,请参阅MDN documentation on Array.reduce

一些提示

  • 尽可能将事情分解为更小的功能。
  • 限制全局变量的使用,但是当你确实需要它时,要保持干净并保持一致
  • 限制在DOM上存储数据(我稍微违反了这一点,但这只是草图代码)
  • 以可重复使用的方式尝试编写代码

这种方法的好处是可以更轻松地添加新功能/更改您构建的内容。例如,如果我们编写一个泛型函数getColumnTotal(selector),它允许您为列的单元格指定jQuery选择器(例如:.priceCell),那么您可以将其重用于其他列,例如quantity

我假设您正在努力实现一个完整的单元格,它显示所有单个订单/行的总和。要做到这一点,我们需要做的就是为每一行计算subtotal,为其添加一个新列,然后重新使用getColumnTotal函数来总结所有子总计。瞧,总计。

请注意,我的代码没有考虑到错误,因此您可能需要处理输入无效quantityprice数据的情况。

&#13;
&#13;
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);
}
&#13;
#TableHead td {
  border-bottom: 1px #000 solid;
}

.orderTotalCell,
#grandTotalCell,
#totalPriceCell {
  text-align: right;
 }

#TableFooter tr:first-child td {
  border-top: 1px #000 solid;
}
&#13;
<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">&ndash;</td>
      <td id="totalPriceCell">&ndash;</td>
      <td id="grandTotalCell">&ndash;</td>
    </tr>
  </tfoot>
</table>

<input type="button" id="xd" value="add row">
&#13;
&#13;
&#13;

答案 3 :(得分:0)

您可以创建一个函数来计算总数,并在添加每一行后调用它,如果您有一些初始值,则在页面加载时调用它。

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')将找到id为'ID'的表的所有行。然后使用每个函数迭代每个tr。然后在每一行中,您可以找到所有类似的td,并使用eq函数获取特定的td。 eq获取元素的索引。

这里正在运行fiddler:https://jsfiddle.net/8a4umvdr/

答案 4 :(得分:0)

您的脚本中存在一些缺陷,我将引导您完成这些缺陷,以便您更好地了解该过程:

  1. 避免使用内联JS 。如果要动态绑定事件,可以使用.on()代替。由于该表存在于DOM就绪,您可以使用$('#Table').on(...)收听删除按钮上的点击事件

  2. 将计算和计算整合到一个函数中。您可以创建一个函数,比如computeSum(),每次修改表时都会调用它:在添加表行或删除表行时调用它。您也可以在运行时调用此函数,这样就不必使用服务器端语言来预先计算起始值。

    • 在下面的示例中,我将获取第5列和第6列中的文本节点(基于零的索引为45),并通过附加{{}将它们转换为float。 1}}在他们面前
    • 我在打印总和时也使用了+函数,因此很好地显示了两位小数。
  3. 修复HTML注入。请记住,要使.toFixed(2)元素有效,它们必须嵌套在<td>中。你似乎意外地将其遗弃了。

  4. 以下是您的代码段的完整功能示例:

    <tr>
    $(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();
    });

    进一步改进

    您可以对我上面的代码进行一些小的改进,但它们被认为是非关键任务,因此我没有在原始答案中包含它们。

    1. <强>扩展即可。如果要计算其他列,则很难一遍又一遍地重写相同的行。相反,我建议您将总和存储在对象中。

    2. 取值。我们正在根据列中的文本节点检索值。有时,您不希望这样 - 您想要在数量和/或价格列中包含货币或其他文本。从这个意义上讲,您可能希望将此类数据存储在自定义HTML5 <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">属性中。

    3. data-
      $(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();
      });