0
<lightning:treeGrid aura:id="accountsTreeComponent"
                    columns="{!v.gridColumns}"
                    data="{!v.gridData}"
                    keyField="accountId"
                    expandedRows="{! v.gridExpandedRows }"
                    isLoading="{! v.isLoading }"
                    ontoggle="{! c.handleRowToggle }"
                    onrowselection="{!c.onRowSelection}"/>

This is how I am using treegrid component.

When I expand a treegrid row, and then collapse it, automatically onrowselection event is fired, which calls onRowSelection action handler in JS controller.

I have made an important observation. This issue occurs in the following scenario:

  1. Expand a row (onrowtoggle fired)
  2. Select a child row(onrowselection fired)
  3. Collapse the parent row (onrowtoggle fired + onrowselection fired)

I believe step 3 internally deselects the child row selected in step 2 which results in firing of onrowselect event. This is certainly a faulty behaviour.

How can I prevent this?

0

I encountered a similar behavior with the LWC Tree Grid. To solve I simply wrapped that specific code in an if statement that checked the length based on the following console result when unchecking a row:

enter image description here

onrowselection={getSelected}

getSelected(event) {
   const selected = event.detail.selectedRows;
   // prevent execution on uncheck
   if(selected.length > 0) {
      // onselection code goes here

   }
}
0

Worked with salesforce support and they found this to be a platform bug that they will be working on as a bug (with the bug id of W-7599458, not sure where I was expected to check back on that?).

So as for now, this is not achievable using the LWC treegrid component.

0

I encountered this issue lately so I worked on a solution to prevent this behavior

My code allows to keep selection persistent for collapsed rows but will also select all child if you select the parent, deselect the parent if you deselect at least one child, select the parent if all child are selected...

Here is the code of the .cmp :

<aura:attribute name="selectedRowsDispo" type="List"/>
<aura:attribute name="currentSelectedDispo" type="List"/>
<aura:attribute name="listToggledId" type="List"/>
<lightning:treeGrid aura:id="tableDispo"
                        columns="{! v.ColumnsDispo }"
                        data="{! v.DataDispo }"
                        keyField="link_dispo"
                        selectedRows="{! v.selectedRowsDispo}"
                        onrowselection="{! c.updateSelectedRows}"
                        ontoggle="{! c.onToggleDispo}"/>

Controller.js :

{ updateSelectedRows: function(cmp, event, helper) {
    console.log("Select");
    helper.updateSelectedRowsDispo(cmp, helper);
},
onToggleDispo: function(cmp, event, helper) {
    console.log("Toggle");
    var toggledId = event.getParam("name");
    var listToggledId = cmp.get("v.listToggledId");
    if (event.getParam("isExpanded") === false) {
        listToggledId.push(toggledId);
    } else {
        const index = listToggledId.indexOf(toggledId);
        if (index > -1) {
            listToggledId.splice(index, 1);
        }
    }
    cmp.set("v.listToggledId", listToggledId);
    var currentSelectedDispo = cmp.get("v.currentSelectedDispo");
    if (currentSelectedDispo.length > 0) {
        cmp.set("v.selectedRowsDispo", currentSelectedDispo);
    }
}});

Regarding the function onToggle, usually when you collapse a parent, salesforce automatically deselect all child, deselecting then automatically the parent. To prevent this I keep in a list the Ids of my collapsed rows. Since Salesforce deselect the child it will trigger onrowselection : Here is my helper.js :

{ updateSelectedRowsDispo: function(cmp, helper) {
    var tempList = [];
    var selectedRows = cmp.find("tableDispo").getSelectedRows();
    var data = cmp.get("v.DataDispo");
    var currentSelectedDispo = cmp.get("v.currentSelectedDispo");
    helper.keepSelectionPersistent(cmp, data, currentSelectedDispo, tempList);

    if (selectedRows.length > 0) {
        selectedRows.forEach(row => {
            tempList.push(row.link_dispo);
        })

        // select and deselect child rows based on header row
        data.forEach(row => {
            // if header was checked and remains checked, do not add sub-rows

            // if header was not checked but is now checked, add sub-rows
            if (!currentSelectedDispo.includes(row.link_dispo) && tempList.includes(row.link_dispo)) {
                if (row.hasOwnProperty('_children')) {
                    row._children.forEach(item => {
                        if (!tempList.includes(item.link_dispo)) {
                            tempList.push(item.link_dispo);
                        }
                    })
                }
            }
            // if header was checked and is no longer checked, remove header and sub-rows
            if (currentSelectedDispo.includes(row.link_dispo) && !tempList.includes(row.link_dispo)) {
                if (row.hasOwnProperty('_children')) {
                    row._children.forEach(item => {
                        const index = tempList.indexOf(item.link_dispo);
                        if (index > -1) {
                            tempList.splice(index, 1);
                        }
                    })
                }
            }
            // if all child rows for the header row are checked, add the header
            // else remove the header
            var allSelected = true;
            if (row.hasOwnProperty('_children')) {
                row._children.forEach(item => {
                    if (!tempList.includes(item.link_dispo)) {
                        allSelected = false;
                    }
                })
            
                if (allSelected && !tempList.includes(row.link_dispo)) {
                    tempList.push(row.link_dispo);
                } else if (!allSelected && tempList.includes(row.link_dispo)) {
                    const index = tempList.indexOf(row.link_dispo);
                    if (index > -1) {
                        tempList.splice(index, 1);
                    }
                }
            }
        })
    }
    cmp.set("v.selectedRowsDispo", tempList);
    cmp.set("v.currentSelectedDispo", tempList);
    console.log(cmp.get("v.currentSelectedDispo"));
},
keepSelectionPersistent: function(cmp, data, currentSelectedDispo, tempList) {
    var toggledRows = cmp.get("v.listToggledId");
    toggledRows.forEach(row => {
        data.forEach(rowData => {
            if (rowData.link_dispo === row) {
                rowData._children.forEach(item => {
                    currentSelectedDispo.forEach(current => {
                        if (current === item.link_dispo) {
                            tempList.push(current);
                        }
                    })
                })
            }
        })
    })
}});

Since I know all rows that were collapsed I use the function keepSelectionPersistent to push in my tempList the Ids of the selected child of my collapsed row. With this I can reinsert them in the selectedRowsDispo.

It may be a bit hard to understand but works like a charm.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.