简体   繁体   English

如何递归求和 jquery 表中的父子层次结构值

[英]How to recursively sum parent child hierarchy value in jquery table

I have parent child hierarchy data loaded from database into html table structure where i need to enter value in some of leaf node.我将父子层次结构数据从数据库加载到 html 表结构中,我需要在某些叶节点中输入值。

When I enter value in any leaf node then recursively do sum in hierarchy up to last parent node.当我在任何叶节点中输入值时,然后递归地在层次结构中求和直到最后一个父节点。

I need to do this using jquery/javascript and html table tree format.我需要使用 jquery/javascript 和 html 表树格式来执行此操作。

This is my html这是我的 html

 //This is textbox change event. $(document).on('change', '.item-balance', function () { if (.$.isNumeric($(this);val())) return false. calculatehierarchybalance($(this);closest('tr')); }). //Below is calculation function. Here problem is that it only sum up to single level instead of all the parent of leaf node. var calculatehierarchybalance = function (currentrow) { var inpctrl = $(currentrow).find(";item-balance"); var _total = 0. $,each(currentrow. function () { var ss = $('tr[data-id=' + $(currentrow);attr('data-parentid') + ']'). //console.log($(ss),attr('data-id'). $(ss);attr('data-parentid')). if (inpctrl:is('input.text')) { _total = _total + Number(inpctrl;val()). } else { _total = _total + Number($(ss).find('td.td-bal').text();trim()). } $(ss).find('td[data-readonly=true]');text(_total). if ($.isNumeric($(ss);attr('data-parentid'))) calculatehierarchybalance($(ss)); }); };
 .table { width: 100%; max-width: 100%; margin-bottom: 1rem; background-color: transparent; }.table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { border-top: 1px solid #e7eaec; border-bottom: 1px solid #e7eaec; line-height: 1.42857; padding: 8px; vertical-align: top; }.table-Balance td { border: 1px solid #eee; }.collapse-tr.toggle { background: url("https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-minus-empty-128.png"); }.expand-tr.toggle { background: url("https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-plus-empty-128.png"); }.toggle { height: 9px; width: 9px; display: inline-block; }.panel-title { color: #fff;important; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <table class="table table-balance" id="tblbl"> <thead> <tr> <th>Cat&#225;logo de Cuentas</th> <th class="text-right">Balance</th> </tr> </thead> <tbody> <tr data-depth="0" class="collapse-tr level0" data-id="81" data-parentid="" data-readonly="true" data-baseaccounttype="1" data-accounttype="1" data-accountid="2"> <td style="padding-left:0px;" class="align-middle"><span class="toggle collapse-tr"></span>1-Activos</td> <td class="text-right td-bal" data-readonly="true"> 0.00 </td> </tr> <tr data-depth="1" class=" level1" data-id="82" data-parentid="81" data-readonly="true" data-baseaccounttype="1" data-accounttype="1" data-accountid="3"> <td style="padding-left:12px;" class="align-middle"><span class=" "></span>1.1-Activos Corrientes</td> <td class="text-right td-bal" data-readonly="true"> 0.00 </td> </tr> <tr data-depth="2" class=" level2" data-id="83" data-parentid="82" data-readonly="true" data-baseaccounttype="1" data-accounttype="2" data-accountid="4"> <td style="padding-left:18px;" class="align-middle"><span class=" "></span>1.1.10-Efectivo y Equivalentes</td> <td class="text-right td-bal" data-readonly="true"> 0.00 </td> </tr> <tr data-depth="3" class=" level3" data-id="84" data-parentid="83" data-readonly="true" data-baseaccounttype="1" data-accounttype="2" data-accountid="5"> <td style="padding-left:24px;" class="align-middle"><span class=" "></span>1.1.10.1-Cajas</td> <td class="text-right td-bal" data-readonly="true"> 0.00 </td> </tr> <tr data-depth="4" class=" level4" data-id="85" data-parentid="84" data-readonly="false" data-baseaccounttype="1" data-accounttype="2" data-accountid="6"> <td style="padding-left:30px;" class="align-middle"><span class=" "></span>1.1.10.1.10-Caja General</td> <td class="text-right td-bal" data-readonly="false"> <input class="form-control text-right input-sm inputdecimal item-balance" id="Balance" name="Balance" placeholder="Ingresar saldo" type="text" value="0.00" /> </td> </tr> <tr data-depth="3" class=" level3" data-id="87" data-parentid="83" data-readonly="true" data-baseaccounttype="1" data-accounttype="2" data-accountid="8"> <td style="padding-left:24px;" class="align-middle"><span class=" "></span>1.1.10.2-Bancos</td> <td class="text-right td-bal" data-readonly="true"> 0.00 </td> </tr> <tr data-depth="4" class=" level4" data-id="88" data-parentid="87" data-readonly="false" data-baseaccounttype="1" data-accounttype="2" data-accountid="9"> <td style="padding-left:30px;" class="align-middle"><span class=" "></span>1.1.10.2.10-Banco #1 (Cambiar Nombre)</td> <td class="text-right td-bal" data-readonly="false"> <input class="form-control text-right input-sm inputdecimal item-balance" id="Balance" name="Balance" placeholder="Ingresar saldo" type="text" value="0.00" /> </td> </tr> <tr data-depth="4" class=" level4" data-id="86" data-parentid="84" data-readonly="false" data-baseaccounttype="1" data-accounttype="2" data-accountid="7"> <td style="padding-left:12px;" class="align-middle"><span class=" "></span>1.2-Dep&#243;sitos sin aplicar</td> <td class="text-right td-bal">0.00 </td> </tr> <tr data-depth="4" class=" level4" data-id="86" data-parentid="84" data-readonly="false" data-baseaccounttype="1" data-accounttype="2" data-accountid="7"> <td style="padding-left:18px;" class="align-middle"><span class=" "></span>1.2.1-Dep&#243;sitos sin aplicar 1</td> <td class="text-right td-bal"> <input class="form-control text-right input-sm inputdecimal item-balance" id="Balance" name="Balance" placeholder="Ingresar saldo" type="text" value="0.00" /> </td> </tr> </tbody> </table>

Expected Output as below image when I entered value in leaf node that will reflect to all related parent node.当我在叶节点中输入将反映到所有相关父节点的值时,预期 Output 如下图所示。 在此处输入图像描述

Any help would be appreciated.任何帮助,将不胜感激。

Thank you.谢谢你。

A bit late for an answer, but I enjoyed giving an answer:)答案有点晚了,但我很喜欢给出答案:)

I chose a bit different approach:我选择了一些不同的方法:

  • create an object that holds the data recursively创建一个以递归方式保存数据的 object
  • make the value "reactive" by using getter s使用getter使值“反应”

I guess neither too efficient nor very scalable, but solves the problem in a logically simple way.我想既不太高效也不太可扩展,但以一种逻辑上简单的方式解决了问题。

 // sum the value of immediate children's values function getRecursiveVal(items) { return items.length? items.reduce((a, c) => a + c.val, 0): 0 } // recursive object getter // gets an item by label function findByLabel(label, item) { if (item.label === label) { return item } else if (item?.length || item?.items?.length) { let ret for (let i = 0; i < item.items.length; i++) { ret = findByLabel(label, item.items[i]) if (ret) { break; } } return ret } } // array to hold the data // if readonly is false, then the item's // beginning val is 0 // if readonly is true, the the items's // beginning val is the sum of its items vals const arr = [ { label: "1-Activos", get val() { return getRecursiveVal(this.items) }, readonly: true, items: [ { label: "1.1-Activos Corrientes", get val() { return getRecursiveVal(this.items) }, readonly: true, items: [ { label: "1.1.10-Efectivo y Equivalentes", get val() { return getRecursiveVal(this.items) }, readonly: true, items: [ { label: "1.1.10.1-Cajas", get val() { return getRecursiveVal(this.items) }, readonly: true, items: [ { label: "1.1.10.1.10-Caja General", val: 0, readonly: false, items: [], }, ], }, { label: "1.1.10.2-Bancos", get val() { return getRecursiveVal(this.items) }, readonly: true, items: [ { label: "1.1.10.2.10-Banco #1 (Cambiar Nombre)", val: 0, readonly: false, items: [], }, ], } ], } ], }, { label: "1.2-Depósitos sin aplicar", get val() { return getRecursiveVal(this.items) }, readonly: true, items: [ { label: "1.2.1-Depósitos sin aplicar 1", val: 0, readonly: false, items: [], }, ], } ] }, ]; // row template function rowHtml(data) { let html = '<tr>' html += `<td>${ data.label }</td>` if (data.readonly) { html += `<td>${ data.val }</td>` } else { html += ` <td> <input data-inputfor="${ data.label }" value="${ Number(data.val) }" /> </td> ` } html += '</tr>' return html } // flattening the object for // HTML table function recTableHtml(item) { let html = rowHtml(item) if (item?.items?.length) { html += item.items.map(e => recTableHtml(e)).join("") } return html } const tbody = document.getElementById("tbody"); function updateTable(container, arr, fn) { container.innerHTML = arr.map(e => fn(e)).join("") } // first paint of the table (function(container) { updateTable(tbody, arr, recTableHtml) })(tbody); jQuery(document).ready(function($) { // general action on input $("body").on("input", "input", function(e) { const thisLabel = this.getAttribute("data-inputfor") const item = findByLabel(thisLabel, arr[0]) item.val = Number($(this).val()) updateTable(tbody, arr, recTableHtml) // setting focus to last char of input // so there's continuous typing var value = $(`[data-inputfor="${thisLabel}"]`).val(); $(`[data-inputfor="${thisLabel}"]`).focus().val('').val(value) }) })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <table> <tbody id="tbody"></tbody> </table>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM