Search code examples
javascriptangulartypescripttreeview

Sum children and acumulate with parents array tree Angular Typescript


enter image description here

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


Solution

  • 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; }