LWC-Custom Tree with indented checkbox with event (3th-Level Hierarchy)

 Sample picture of the custom lightning web component tree with the indented checkbox.



Sample JSON

[
    {
        "Items": [
            {
                "Items": [
                    {
                        "name""Dash Absolute Return Bond Fund",
                        "recId""000007654"
                    },
                    {
                        "name""Dash Investment Management LLC",
                        "recId""00004445"
                    },
                    {
                        "name""Dash Institutional Trust Company",
                        "recId""000077788"
                    },
                    {
                        "name""Dash Institutional Trust Company",
                        "recId""000088995"
                    },
                    {
                        "name""Dash Institutional Trust Company",
                        "recId""00001212"
                    },
                    {
                        "name""Dash Financial Management Inc",
                        "recId""01010101"
                    },
                    {
                        "name""Dash Investment Management LLC",
                        "recId""22223333"
                    },
                    {
                        "name""Dash Advisors (UK) Limited",
                        "recId""45645612"
                    }
                ],
                "name""DASH INVESTMENT MANAGEMENT",
                "recId""000000123"
            }
        ],
        "name""DASH GROUP",
        "recId""00001234"
    }
]

CustomTree.html
Make an LWC component that can be used as a reusable component.

<template>
    <div class="slds-text-longform" id="dashTree">
        <ul class="myUL">
            <!--=================LEVEL-1 ITERATION==========================-->
            <template for:each={records} for:item="record" for:index="parentRec">
                <li key={record.recId}>
                    <!--=================LEVEL-2 ITERATION==========================-->
                    <template if:true={record.Items}>
                        <span class="caret">
                            <template if:true={showCheckBox}>
                                <input type="checkbox" value={record.recId} onclick={collectItem} class="chkTree_1">&nbsp;&nbsp;
                            </template>
                            <span class="onHover">{record.name}</span>
                        </span>
                        <ul class="nested">
                            <template for:each={record.Items} for:item="childRec_1" for:index="childRec_idx1">
                                <li key={childRec_1.recId}>
                                    <!--=================LEVEL-3 ITERATION==========================-->
                                    <template if:true={childRec_1.Items}> 
                                        <span class="caret">
                                            <template if:true={showCheckBox}>
                                                <input type="checkbox" value={childRec_1.recId} onclick={collectItem} class="chkTree_1">&nbsp;&nbsp;
                                            </template>
                                            <span class="onHover">{childRec_1.name}</span>
                                        </span>
                                        <ul class="nested">
                                            <template for:each={childRec_1.Items} for:item="childRec_2" for:index="childRec_idx2">
                                                <li key={childRec_2.recId}>
                                                    <template if:true={showCheckBox}>
                                                        <input type="checkbox" value={childRec_2.recId} onclick={collectItem} class="chkTree_1">&nbsp;&nbsp;
                                                    </template>
                                                    <span class="onHover">{childRec_2.name}</span>
                                                </li>
                                            </template>
                                        </ul>
                                    </template>
                                    <template if:false={childRec_1.Items}>
                                        <template if:true={showCheckBox}>
                                            <input type="checkbox" value={childRec_1.recId} onclick={collectItem} class="chkTree_1">&nbsp;&nbsp;
                                        </template>
                                        <span class="onHover">{childRec_1.name}</span>
                                    </template>
                                </li>
                            </template>
                        </ul>
                    </template>
                    <template if:false={record.Items}>
                        <template if:true={showCheckBox}>
                            <input type="checkbox" value={record.recId} onclick={collectItem} class="chkTree_1">&nbsp;&nbsp;
                        </template>
                        <span class="onHover">{record.name}</span>
                    </template>
                </li>
            </template>
        </ul>
    </div>
</template>

CustomTree.js

import { LightningElementapitrack } from 'lwc';

export default class CustomTree extends LightningElement {
    @api searchValue = '';
    @api showCheckBox = false;
    @api records;
    @track error;

    renderedCallback() {
        //alert("Welcome to LWC Constructor!");
        let toggler = this.getElementsByClassName("caret");
        //alert(toggler.length)
        var i;

        for (i = 0i < toggler.lengthi++) {
            toggler[i].addEventListener("click"function () {
                this.parentElement.querySelector(".nested").classList.toggle("active");
                this.classList.toggle("caret-down");
            });
        }
    }

    collectItem(event) {
        try {
            //alert(event.target.value + ', ' + event.target.checked);
            var tempList = [];
            let toggler = this.template.querySelectorAll(".chkTree_1");
            var i;
            for (i = 0i < toggler.lengthi++) {
                //alert(toggler[i].value + ', ' + toggler[i].checked);
                if (toggler[i].checked) {
                    tempList.push(toggler[i].value);
                }
            }
            //alert("Child: " + tempList);

            //Passing selected item to parent
            const custEvent = new CustomEvent(
                'select', {
                detail: { 'selectedItems': tempList }
            });
            this.dispatchEvent(custEvent);
        }
        catch (exception) {
            alert(exception);
        }
    }

    parseResponse(result) {
        //alert(JSON.stringify(result));
        let parseData = JSON.parse(JSON.stringify(result));
        //alert(JSON.stringify(parseData['Items']));
        for (let i = 0i < parseData.lengthi++) {
            if (parseData['Items'] != undefined) {
                parseData[i]._children = parseData['Items'];

                //ITERATION CODE FOR LEVEL-2
                for (let j = 0j < parseData[i]._children.lengthj++) {
                    if (parseData[i]._children[j]['Items'] != undefined) {
                        parseData[i]._children[j]._children = parseData[i]._children[j]['Items'];

                        //ITERATION CODE FOR LEVEL-3
                        for (let k = 0k < parseData[i]._children[j]._children.lengthk++) {
                            if (parseData[i]._children[j]._children[k]['Items'] != undefined) {
                                parseData[i]._children[j]._children[k]._children = parseData[i]._children[j]._children[k]['Items'];
                            }
                            delete parseData[i]._children[j]._children[k]['Items'];
                        }
                    }
                    delete parseData[i]._children[j]['Items'];
                }
            }
        }
        delete parseData['Items'];

        this.records = parseData;
        alert(JSON.stringify(parseData));

        return this.records;
    }
}

CustomTree.css

liul.myUL {
  list-style-typenone;
  margin-left0;
  padding-left17px;
  line-height:25px;
}

.myUL {
  margin0;
  padding0;
}

.onHover:hover{
  background-color:lightskyblue;
}

.caret {
  cursorpointer;
  -webkit-user-selectnone/* Safari 3.1+ */
  -moz-user-selectnone/* Firefox 2+ */
  -ms-user-selectnone/* IE 10+ */
  user-selectnone;
}

.caret::before {
  content"\25B6";
  colorblack;
  displayinline-block;
  margin-right6px;
}

.caret-down::before {
  -ms-transformrotate(90deg); /* IE 9 */
  -webkit-transformrotate(90deg); /* Safari */
  transformrotate(90deg);  
}

.nested {
  displaynone;
}

.active {
  displayblock;
}


How to reuse custom component

use the below code in your parent component as child.

<c-custom-tree records={bankingRecords} 
                 show-check-box={showCheckBox_PH} 
                 onselect={collectItem}>
</c-custom-tree>

pass parameter as above mentioned.

records= Sample JSON

show-check-box = true/false

onselect = Used JS Method to get selected items value.

Script to handle the event of on select of checkbox

collectItem(event) {
   var selectedItems = event.detail.selectedItems;
   if (selectedItems.length > 0)
       alert("Selected Items: " + selectedItems);
}


Comments

Popular posts from this blog

Salesforce WebService Integration

Connect Salesforce REST API Using JavaScript

SFDX Simplified