0

*Edit - link to playground here.

I'm running into this issue trying to build select all/deselect all for a hierarchy table built in lwc tree grid and am stuck on this bug firing the onselect when trying to deselect rows programmatically.

I have a 3 level hierarchical data table and when a user de-selects from the lowest level (L3) of any parent, when the parent is unselected the on-toggle fires, which for some reason fires the onrowselect event which is incorrect. Following my example, when the onrowselect fires it still hasn't processed my L1 de-select since it had unselected the L2 and L3 and toggled off the L2 and and so it re-adds the L2 and L3's including any other L2's and L3's that were under L1 but were not explicitly selected before.

how has anyone been able to use this component given this 'known' issue?

4
  • 1
    Could you create a Playground that demonstrates this so we don't have to build from scratch? – sfdcfox Apr 27 '20 at 16:43
  • Yes absolutely, still new to all this so will take me a minute but I will update the post the minute I have one ready. thank you! – user7994540 Apr 27 '20 at 17:34
  • Okay @sfdcfox just added a link to the playground. I am dealing with a 3 level hierarchy but the issue presents itself for N so my simplified 2 level playground should still demonstrate that onselect is being fired when a user toggles the parent row after selecting a child. In particular I am trying to handle the scenario where a user selects a child and I then determine what parents need to also be deselected if any and then update the selectedrows and expandedrows track variables but getting stuck on this bug. – user7994540 Apr 27 '20 at 18:23
  • Any luck with the the playground link? – user7994540 Apr 28 '20 at 18:52
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 :

  1. Expand a row (onrowtoggle fired)
  2. Select a child row(onrowselection fired)
  3. 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.

2
  • 1
    That's not LWC but Aura. – Martin Lezer Jan 14 at 16:30
  • I agree, but if he wants, the algorithm is good. LWC and Aura are pretty close. – Raphaël Loyant Jan 15 at 13:57

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.