Im working on Angular 11 project i need show a tree view with an input by row, the user can change values of input and i need recalculate totals for every change on input. I want to calculate the sum of the child nodes and save that on parent node for show the new totals.
This is the dataStructure and expected results on "total" key
dataTreeView = [
{
"account_id": "42",
"account_parent": null,
"name": "Ingresos de actividades ordinarias",
"total": 17, // expected result sum 5 12 = 17
"children": [
{
"account_id": "422",
"account_parent": "42",
"name": "Ventas",
"total": 5
},
{
"account_id": "421",
"account_parent": "42",
"name": "Devoluciones en ventas",
"total": 12
}
]
},
{
"account_id": "55",
"account_parent": null,
"name": "Costos de ventas y operación",
"total": 24, // expected result 19 5
"children": [
{
"account_id": "552",
"account_parent": "55",
"name": "Costos de la mercancía vendida",
"total": 19, // expected result sum 5 14 = 19
"children": [
{
"account_id": "5524",
"account_parent": "552",
"name": "Devoluciones en compras de inventario",
"total": 14, // expected result sum 4 10 = 14
"children": [
{
"account_id": "55241",
"account_parent": "5524",
"name": "Descuentos",
"total": 10
},
{
"account_id": "55242",
"account_parent": "5524",
"name": "Otros",
"total": 4
},
]
},
{
"account_id": "5523",
"account_parent": "552",
"name": "Costos del inventario",
"total": 5
},
]
},
]
}
]
I try with reduce but not working
data.reduce(function x(r, a) {
a.total = a.total || (Array.isArray(a.children) &&
a.children.reduce(x, 0)) || 0;
return r a.total;
}, 0)
I appreciate your help with this solution
Thanks and regards
CodePudding user response:
If you have values for total
and other nested value which sums to a new value, you could move o.total
to the end of the expression and evaluate the array first.
const
updateTotal = (r, o) => r (
o.total = (o.children || []).reduce(updateTotal, 0) || o.total || 0
),
data = [{ account_id: "42", account_parent: null, name: "Ingresos de actividades ordinarias", total: 10, children: [{ account_id: "422", account_parent: "42", name: "Ventas", total: 5 }, { account_id: "421", account_parent: "42", name: "Devoluciones en ventas", total: 12 }] }, { account_id: "55", account_parent: null, name: "Costos de ventas y operación", total: 0, children: [{ account_id: "552", account_parent: "55", name: "Costos de la mercancía vendida", total: 0, children: [{ account_id: "5524", account_parent: "552", name: "Devoluciones en compras de inventario", total: 0, children: [{ account_id: "55241", account_parent: "5524", name: "Descuentos", total: 10 }, { account_id: "55242", account_parent: "5524", name: "Otros", total: 4 }] }, { account_id: "5523", account_parent: "552", name: "Costos del inventario", total: 5 }] }] }];
data.reduce(updateTotal, 0);
console.log(data)
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
For each element of your array you want to set the value total
that is the sum of all total
inside children
, right?
data.forEach(el => {
el.total = el.total el.children.reduce((a,b) => a.total b.total);
}
CodePudding user response:
You need a recursive function to traverse your tree
const data = [
{
"account_id": "42",
"account_parent": null,
"name": "Ingresos de actividades ordinarias",
"children": [
{
"account_id": "422",
"account_parent": "42",
"name": "Ventas",
"total": 5
},
{
"account_id": "421",
"account_parent": "42",
"name": "Devoluciones en ventas",
"total": 12
}
]
},
{
"account_id": "55",
"account_parent": null,
"name": "Costos de ventas y operación",
"children": [
{
"account_id": "552",
"account_parent": "55",
"name": "Costos de la mercancía vendida",
"children": [
{
"account_id": "5524",
"account_parent": "552",
"name": "Devoluciones en compras de inventario",
"children": [
{
"account_id": "55241",
"account_parent": "5524",
"name": "Descuentos",
"total": 10
},
{
"account_id": "55242",
"account_parent": "5524",
"name": "Otros",
"total": 4
},
]
},
{
"account_id": "5523",
"account_parent": "552",
"name": "Costos del inventario",
"total": 5
},
]
},
]
}
]
function addTotalFromChildren(arr){ //Important function
arr.forEach(obj => { //For each element of the array
if("children" in obj) { //Check if element has children
addTotalFromChildren(obj.children) //Then, we need to calculate the add total for those children
obj.total = obj.children.reduce((a, v) => a = v.total, 0) //then we calculate the sum of those total
} //Else it already has a total property
})
}
addTotalFromChildren(data)
console.log(data)
I added some comments to explain the code.
Let me know if you don't understand something in the comments below.