I think there are are two ways to achieve what you want:
- Don't change underlying data structure but change UI markup handle data structure.
- Change underlying data structure but keep UI markup simple.
I chose option 2 and was able to get this output:
Link to playground: https://developer.salesforce.com/docs/component-library/tools/playground/KG-dO5AL/1/edit
app.html:
<template>
<table>
<thead>
<th>Name</th>
</thead>
<tbody>
<template for:each={tableData} for:item="rowData">
<tr key={rowData.Id} class={rowData.rowStyle}>
<td>
<span style={rowData.nameStyle}>
<lightning-icon icon-name={rowData.iconName}
size=x-small
onclick={showOrHideChildrenRows}
data-rowid={rowData.Id}
data-expanded="false">
</lightning-icon>
{rowData.Name}
</span>
</td>
</tr>
</template>
</tbody>
</table>
</template>
app.js:
import { LightningElement, track } from "lwc";
export default class App extends LightningElement {
@track
tableData =[
{
Name: "United States",
Id: 1,
iconName: "utility:chevronright",
parentId : null,
rowStyle : "",
nameStyle : ""
},
{
Name: "Massachusetts",
Id: 2,
iconName: "utility:chevronright",
parentId: 1,
rowStyle : "hide",
nameStyle : "margin-left:10px;"
},
{
Name: "Boston",
Id: 3,
iconName: "",
parentId: 2,
rowStyle : "hide",
nameStyle : "margin-left:20px;"
},
{
Name: "New York",
Id: 4,
iconName: "",
parentId : 1,
rowStyle : "hide",
nameStyle : "margin-left:20px;"
},
{
Name: "Vatican City",
Id : 5,
iconName: "",
parentId : null,
rowStyle : "",
nameStyle : ""
},
{
Name: "Canada",
Id : 6,
iconName: "utility:chevronright",
parentId : null,
rowStyle : "",
nameStyle : ""
},
{
Name: "Ontario",
Id : 7,
iconName: "",
parentId : 6,
rowStyle : "hide",
nameStyle : "margin-left:10px;"
},
{
Name: "Alberta",
Id : 8,
iconName: "",
parentId : 6,
rowStyle : "hide",
nameStyle : "margin-left:10px;"
}
];
showOrHideChildrenRows(event){
let rowId = event.target.dataset.rowid;
let isExpanded = event.target.dataset.expanded;
event.target.iconName = JSON.parse(isExpanded) ? "utility:chevronright": "utility:chevrondown";
event.target.dataset.expanded = JSON.stringify(!JSON.parse(isExpanded));
this.tableData = this.tableData.map((obj) => {
if(obj.parentId == rowId && !JSON.parse(isExpanded)){
obj.rowStyle = "";
}
if(obj.parentId == rowId && JSON.parse(isExpanded)){
obj.rowStyle = "hide";
}
return obj;
});
console.log(this.tableData);
}
}
Each element in the data structure has these special attributes:
parentId
- to relate each element to its parent element.rowStyle
- to hide or show children elements.nameStyle
- to apply proper indentation to parent elements.