skip to Main Content

I would like the calculate depth method to calculate the depth correctly and instead it is calculating in reverse assigning the first element with depth 2, the second with depth 1 and the third with depth 0, perhaps I need to create a new method where it receives the revisionData and then see item by item. And does not calculate for any reason a depth greater than 2.

<template>
      <acc-data-table-v2
            :data="revisionData"
            :columns="columns"
            primaryColumn="id"
            treeRowKey="id"
            row-key="id"
            :treeProps="{children: 'children'}"
            :row-class-name="tableRowClassName"
            >

            <template v-slot:subflowsRevisionsDescriptionTemplate="slotProps">
                <div>
                        <div :style="{ marginLeft: calculateMarginLeft(calculateDepth(slotProps.scope.row)) }">
                            <div v-if="slotProps.scope.row.step_id">
                                {{ slotProps.scope.row.step.description }} 
                            </div>
                            <div v-if="!slotProps.scope.row.step_id">
                                {{ slotProps.scope.row.description }} 
                            </div>
                        </div>
                </div>
            </template>
      </acc-data-table-v2>
</template>


<script>
export default {
  data() {
    return {
      revisionData: [
        {
          id: 1, //depth: 0
          name: 'Parent 1',
          children: [
            {
              id: 11, //depth: 1
              name: 'Child 1.1',
              children: [
                {
                  id: 111, //depth: 2
                  name: 'Grandchild 1.1.1'
                },
              ]
            },
            {
              id: 12, //depth: 1
              name: 'Child 1.2'
            }
          ]
        },
        {
          id: 2, //depth:0
          name: 'Parent 2',
          children: [
            {
              id: 21, //depth: 1
              name: 'Child 2.1'
            }
          ]
        }
      ]
    };
  },
  methods: {
        calculateMarginLeft(depth) {
            const marginLeft = depth * 12 + 'px';
            return marginLeft;
        },
        calculateDepth(item) {
            let depth = 0;
            let parent = item;
            while (parent.children && parent.children.length > 0) {
                depth++;
                parent = parent.children[0];
            }
            return depth;
        },
  }
};
</script>

3

Answers


  1. Ok so you can try in modifying the code a bit ig

    calculateDepth(item) {
      let depth = 0;
      let parent = item;
      // if there is no parent or any parent doesnt have child elemen`
      while (parent && parent.children && parent.children.length > 0) {
        depth++;
        parent = parent.children[0]; //  first child
      }
      return depth;
    }
    

    and after that also calculate the margin left based on teh depth factor

    calculateMarginLeft(depth) {
      const marginLeft = depth * 12 + 'px';
      return marginLeft;
    }
    

    I think it should work!

    Login or Signup to reply.
  2. It’s quite a simple recursive function:

    Iterate over the array and assign each element the current depth. If an element has children call the function recusively with the incremented depth. The maximum depth is the maximum depth of any of the children.

    function calcDepth(array, d) {
      let maxDepth = d;
      for (let elem of array) {
        elem.depth = d;
        if (elem.children?.length)
          maxDepth = Math.max(maxDepth, calcDepth(elem.children, d + 1));
      }
      return maxDepth;
    }
    
    let test = [ 
      { 
        id: "1", 
        children: [
          { 
            id: "1.1", 
            children: []
           }
        ]
      },
    { 
        id: "2", 
        children: [
          { 
            id: "2.1", 
            children: [
              {
                id: "2.1.1",
                children: [
                  {
                    id: "2.1.1.1"
                  }
                ]
              }
            ]
           }
        ]
      }  
    ];
    
    let max = calcDepth(test,0);
    console.log(test);
    console.log("MaxDepth: ", max);
    Login or Signup to reply.
  3. This is a classic tree depth problem.

    Update your code like the following:

    • create a computed value revisionDataWithDepth that is a copy recursiveData with an additional field depth
    • pass this revisionDataWithDepth to your :data
    • to get left margin call calculateMarginLeft(slotProps.scope.row.depth)
    <template>
          <acc-data-table-v2
                :data="revisionDataWithDepth"
                :columns="columns"
                primaryColumn="id"
                treeRowKey="id"
                row-key="id"
                :treeProps="{children: 'children'}"
                :row-class-name="tableRowClassName"
                >
    
                <template v-slot:subflowsRevisionsDescriptionTemplate="slotProps">
                    <div>
                            <div :style="{ marginLeft: calculateMarginLeft(slotProps.scope.row.depth) }">
                                <div v-if="slotProps.scope.row.step_id">
                                    {{ slotProps.scope.row.step.description }} 
                                </div>
                                <div v-if="!slotProps.scope.row.step_id">
                                    {{ slotProps.scope.row.description }} 
                                </div>
                            </div>
                    </div>
                </template>
          </acc-data-table-v2>
    </template>
    
    
    <script>
    export default {
      data() {
        return {
          revisionData: [
            {
              id: 1, //depth: 0
              name: 'Parent 1',
              children: [
                {
                  id: 11, //depth: 1
                  name: 'Child 1.1',
                  children: [
                    {
                      id: 111, //depth: 2
                      name: 'Grandchild 1.1.1'
                    },
                  ]
                },
                {
                  id: 12, //depth: 1
                  name: 'Child 1.2'
                }
              ]
            },
            {
              id: 2, //depth:0
              name: 'Parent 2',
              children: [
                {
                  id: 21, //depth: 1
                  name: 'Child 2.1'
                }
              ]
            }
          ]
        };
      },
      computed: {
        revisionDataWithDepth: function() {
          // create local function that creates a copy of revisionData with depth included
          function withDepth(revisions, currentDepth) {
            if (!revisions || !revisions.length) {
              return [] // or return undefined
            }
        
            const revisionsWithDepth = [];
            for (const revision of revisions) {
              const revWithDepth = { ...revision };
              revWithDepth.depth = currentDepth;
              revWithDepth.children = withDepth(revision.children, currentDepth + 1);
              revisionsWithDepth.push(revWithDepth);
            }
            return revisionsWithDepth;
          }
          return withDepth(this.revisionData, 0);
        }
      }
      methods: {
            calculateMarginLeft(depth) {
                const marginLeft = depth * 12 + 'px';
                return marginLeft;
            },
      }
    };
    </script>
    

    Tip: you can even use a one-liner for withDepth:

    function withDepth(revisions, depth) {
      return (revisions ?? []).map(revision => ({ ...revision, depth, children: withDepth(revision.children, depth + 1) }))
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search