I encountered this issue lately so I worked on a solution to prevent this behavior :
- Expand a row (onrowtoggle fired)
- Select a child row(onrowselection fired)
- Collapse the parent row (onrowtoggle fired + onrowselection fired)
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.