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>
This is a classic tree depth problem.
Update your code like the following:
revisionDataWithDepth
that is a copy of revisionData
with an additional field depth
revisionDataWithDepth
to your :data
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) }))
}