+ Start a Discussion
Keith PatellaKeith Patella 

Lightning Tree Component How do you dynamically select an item and expand the items

I'm using the lightning tree component and I'm trying to dynamically select an item after Init through an event and want all parent nodes expanded. I have a separte lighting component that the user selects and item and then an event is passed to my component with the Tree containing the Tree Node Name I want to select. This is all working fine but I can't get the lighting:tree component to work.

The expanded issue:
My java script code works to the point of setting all the expanded=true flags for all parent items of the item I want selected but it never renders the children. I can see the expanded icon changed but none of the children are rendered. If I expand everything in the Init handler it displays the tree correctly but on the event java script to change the selected item it just changes the expanded icon and all text is the same.

The Selection Issue: I'm not sure how to select an Item in the tree or what java script I need to make this happen. Any help would be appreciated.

 
Alain CabonAlain Cabon
Hi Keith,

I reproduced your case.

Only expanded=false is working but not expanded=true ( we can only see the expanded icons changed at the "viewing" level without showing the "hidden" children as expected ).

We have very few alternatives. It's more like a defect than the correct wanted behavior (why does expanded=false work and not the opposite?).
 
Ravi Dutt SharmaRavi Dutt Sharma
I created a simple component to check this. On click of a button, it is expanding the tree as expected.

Component:
<aura:component implements="force:appHostable" >
	<aura:handler name="init" value="{!this}" action="{!c.init}" />
    <aura:attribute name="items" type="Object" access="PRIVATE"/>
    <lightning:tree items="{! v.items }" header="Roles"/>
    
    <lightning:button variant="base" label="Expand Eastern Sales Director" title="Expand Eastern Sales Director" onclick="{!c.expand}"/>
</aura:component>

Controller:
({
    init: function (component, event, helper) {
        var items = [{
            "label": "Western Sales Director",
            "name": "1",
            "expanded": true,
            "items": [{
                "label": "Western Sales Manager",
                "name": "2",
                "expanded": true,
                "items" :[{
                    "label": "CA Sales Rep",
                    "name": "3",
                    "expanded": true,
                    "items" :[]
                },{
                    "label": "OR Sales Rep",
                    "name": "4",
                    "expanded": true,
                    "items" :[]
                }]
            }]
        }, {
            "label": "Eastern Sales Director",
            "name": "5",
            "expanded": false,
            "items": [{
                "label": "Easter Sales Manager",
                "name": "6",
                "expanded": true,
                "items" :[{
                    "label": "NY Sales Rep",
                    "name": "7",
                    "expanded": true,
                    "items" :[]
                }, {
                    "label": "MA Sales Rep",
                    "name": "8",
                    "expanded": true,
                    "items" :[]
                }]
            }]
        }];
        component.set('v.items', items);
        console.log('Values have been set');
    },
    
    expand : function(component, event, helper){
        var items = [{
            "label": "Western Sales Director",
            "name": "1",
            "expanded": true,
            "items": [{
                "label": "Western Sales Manager",
                "name": "2",
                "expanded": true,
                "items" :[{
                    "label": "CA Sales Rep",
                    "name": "3",
                    "expanded": true,
                    "items" :[]
                },{
                    "label": "OR Sales Rep",
                    "name": "4",
                    "expanded": true,
                    "items" :[]
                }]
            }]
        }, {
            "label": "Eastern Sales Director",
            "name": "5",
            "expanded": true,
            "items": [{
                "label": "Easter Sales Manager",
                "name": "6",
                "expanded": true,
                "items" :[{
                    "label": "NY Sales Rep",
                    "name": "7",
                    "expanded": true,
                    "items" :[]
                }, {
                    "label": "MA Sales Rep",
                    "name": "8",
                    "expanded": true,
                    "items" :[]
                }]
            }]
        }];
        component.set('v.items', items);
    }
})

On click of the button, I am just setting expanded as true for Eastern Sales Director. Are you setting the items array after manipulating it?
 
Tom Sullivan (Sully)Tom Sullivan (Sully)
Keith, my client had the same situation.  The only way we could get it to work is to re-obtain the full set of data from the back-end and then set the expanded property to true.  This would be consistent with what Ravi did, except that he re-created the data inline.
Philippe UyttendaelePhilippe Uyttendaele
Hello Everyone,
Great news !!!
I have been puzzling on this all day long and managed !

The issue seems to come from the fact that the tree does not record a refresh as all items are the same.
In order to make it happen, you can append and remove space at the end of the lable of the item that you want to toggle.

thus at the location where you toggle expanded = true, place the space at the end of your label.
Let me give a little context on my example = i have a tree on three level. What i need to record is the combination of the 3 items at the same time. Thus selecting first level or second level result in expanding the tree while selecting the last level result in processing.
 
// the names of my items are following the following structure :
// 0  ------ First item
// 0.0 -------- First item - sub first
// {RealName} ------- Last level that i want to take action upon
// ...
// {RealName}
// 0.1 First item - sub second
// {RealName} ------- Last level that i want to take action upon
// ...
// {RealName}
// 1 Second item
// 1.0 second item - sub first
// 1.1 second item - sub secon
// ...


handleSelect: function (cmp, event, helper) {
        var itemSelected = event.getParam('name') ;

        var patt = new RegExp("^[0-9]+(\\.[0-9]+)?$");
        if(patt.test(itemSelected)){

            var items =cmp.get('v.items');
            var depth = itemSelected.split(".");
            if (depth.length == 1)
            {
                items[parseInt(depth[0], 10)].expanded = !items[parseInt(depth[0], 10)].expanded;
                var theLabel = items[parseInt(depth[0], 10)].label;
                theLabel.endsWith(" ")?items[parseInt(depth[0], 10)].label = theLabel.trim():items[parseInt(depth[0], 10)].label = theLabel + " ";//needed to patch SF bug...
            }else if (depth.length == 2)
            {
                items[parseInt(depth[0], 10)].items[parseInt(depth[1], 10)].expanded =
                    !items[parseInt(depth[0], 10)].items[parseInt(depth[1], 10)].expanded;
                var theLabel = items[parseInt(depth[0], 10)].items[parseInt(depth[1], 10)].label;
                theLabel.endsWith(" ")?items[parseInt(depth[0], 10)].items[parseInt(depth[1], 10)].label = theLabel.trim():items[parseInt(depth[0], 10)].items[parseInt(depth[1], 10)].label = theLabel + " ";//needed to patch SF bug...
            }else
            {
                //ERROR
                alert("ERROR - Should be an impossible case... - Please Contact the System Admin explaining how you got here.");
            }
            cmp.set('v.items',items);
            else { 
            //Manage what happens when your last level is selected
            } 
},

Hope it will get many ppl to get this fixed.
 
Srini GrandhiSrini Grandhi
Philippe,
Your solution worked for me. I modified your code to add an extra white space or delete if it already exists (so that the labels do not grow forever).
I do not understand why Salesforce did not provide simple javascript functions for expanding/collapsing the tree nodes. They are absolutely needed.