Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect row stays expanded after sorting an EuiInMemoryTable #820

Closed
peteharverson opened this issue May 11, 2018 · 7 comments
Closed
Assignees
Labels

Comments

@peteharverson
Copy link

For an EuiInMemoryTable with expanded rows, if you expand a row, then sort the rows by clicking on a column header, the same row number stays expanded, showing the content for the item that was previously in that position prior to sorting. The expanded content should move to its new page/row position, or alternatively all rows should be collapsed on sorting.

e.g. expand first row, sorted by decreasing severity:
image

then sort by increasing severity - first row stays expanded, but showing content for previous item in that position:
image

Found in version 0.0.46

@chandlerprall
Copy link
Contributor

I don't think we can properly support sortable columns when the items don't have associated IDs. The IDs we auto-assign are based on their position in the data, and sorting fundamentally alters this association.

You've said before that this data has no guaranteed, unique identifier. You could either stamp the item's original index within the data as its ID, or you could get a hash of the object (e.g. with object-hash to use instead.

I can also add a check to EuiTable that console.errors when sorting is enabled but the first (any?) item doesn't return an item id when passed to EuiBasicTable::itemId to help catch and resolve this case in the future.

@peteharverson
Copy link
Author

Looking at the code for the renderItemRow() function in basic_table.js, am I right in thinking that if selection is not enabled on the table (which it isn't in our case), then the rowIndex is used to check whether the row is expanded in itemIdToExpandedRowMap. In which case, any itemId property I set on the row data would be ignored?

If so, should this behavior be changed, allowing for an itemId property to be checked even if selection is not enabled on the table?

Or as a workaround is there some way of collapsing all rows if the user does a sort?

@chandlerprall
Copy link
Contributor

Indeed. As itemId only works if selection is present (as selection describes how to get the item's id), and passing selection has other side effects, I think the best option is to expose a catch-all table update that can be used to clear the expanded item map.

EuiBasicTable implements an onChange callback that happens anytime sorting or pagination is updated, and EuiInMemoryTable can be made to expose the same, and you can listen for that event and update the expanded item map. How does that sound?

@peteharverson
Copy link
Author

Is using itemId for tables without selection an option? Or is the only viable option clearing the expanded item map if the user sorts or pages the data? The functionality does currently work in EuiInMemoryTable with pagination, so losing that by clearing the expanded item map in onChange to prevent it breaking on sorting would seem a shame.

@chandlerprall
Copy link
Contributor

I wouldn't want to assume a field named itemId is present, and it also prescribes the incoming data's format.

Adding a new property onto the table that duplicates selection's functionality is possible but care would be needed to add proptype logic that selection and the new prop are mutually exclusive. It also adds more complexity to the table code.

As the table components' functionality includes a dependency on having IDs outside of selectables, and providing the UI consistency around if/when expanded rows collapse, I do think adding a more generic itemId makes sense. I wonder if selection.itemId could even be migrated away from - thoughts @cjcenizal ?

@cjcenizal
Copy link
Contributor

I think we're definitely on the right track here! I do think that this issue is evidence that selection.itemId unnecessarily couples the concept of item IDs with selection, and we should migrate away from that.

Here's what I suggest:

  • Remove selection.itemId
  • Add a prop called itemId, which acts as selection.itemId currently does
  • If feasible, add the onChange prop as Chandler suggests

The first two will solve Pete's issue, per Chandler's suggestion to supply a UUID to each row on the client-side.

I suggest the last bullet since I think it's a design flaw if EuiInMemoryTable and EuiBasicTable don't adhere to the Liskov substitution principle. I think it's a safe assumption for people to make that if EuiBasicTable supports a prop, then EuiInMemoryTable should too, since the docs present the latter as a more robust/featureful version of the former.

@chandlerprall
Copy link
Contributor

Turns out onChange is currently exposed via search={{onChange: () => {}}} prop on EuiInMemoryTable. It does have a built-in side effect that if it returns a falsey value the in-memory table assumes the data update will be done by the parent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants