-
Notifications
You must be signed in to change notification settings - Fork 353
Description
Use Case
I'm building a table that is populated by rows that are POJOs which combine info from multiple E-D models. Example psuedocode:
loadData = task(async () => {
const data1 = await this.store.query('model1', {});
const data2 = await this.store.query('model2', {});
return data1.map(d => {
return { id: data1.id, name: data2.name };
});
});
get rows() { return this.loadData.lastSuccessful.value ?? []; }
This table allows the user to refresh the current page, change pages, and select multiple items.
The Issue I'm Seeing
Since we recreate the rows whenever the paging or refresh occurs, the references will no longer match what may have been in the previous selection array.
So, I found selectionMatchFunction which was added ~v3.0 which is seemingly meant to address this issue. It works for the most part - it correctly renders rows as selected based on my own criteria defined in selectionMatchFunction (compare ID instead of object ref).
The issue is that the select function in the TableRowMeta class doesn't seem to respect the selectionMatchFunction. I think there are two main areas here to address:
- The use of
Setto maintain uniqueness of selected elements is always going to do an object ref compare - Even if we converted the
Setto anArray, we'd need to update any functions that add/remove elements or do equality checks to useselectionMatchFunctionin the same way we do for theisSelectedandisGroupSelectedCPs.
For example, in the range selection branch within this function we add the rows to the Set, assuming that any dupes will be removed, without asking selectionMatchFunction if they are actually dupes:
ember-table/addon/-private/collapse-tree.js
Lines 188 to 197 in f9d05b3
| let { _lastSelectedIndex } = tree; | |
| let isFirstIndexDefined = typeof _lastSelectedIndex === 'number'; | |
| let minIndex = isFirstIndexDefined ? Math.min(_lastSelectedIndex, rowIndex) : rowIndex; | |
| let maxIndex = isFirstIndexDefined ? Math.max(_lastSelectedIndex, rowIndex) : rowIndex; | |
| for (let i = minIndex; i <= maxIndex; i++) { | |
| selection.add(tree.objectAt(i)); | |
| } |
The result of this is that we end up with either 1) dupes in the selection array, or 2) elements not being un-selected when they should be.
Brain dump over - I hope I explained this well enough. When I get a few minutes this week I'll put together a gist. If this seems like a real issue to folks, I can put together a PR.