-
-
Notifications
You must be signed in to change notification settings - Fork 173
fix(BTableLite): Use primary key to persist row-details state when items change #2871
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
fix(BTableLite): Use primary key to persist row-details state when items change #2871
Conversation
|
|
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Comment |
…ems change Co-authored-by: VividLemon <[email protected]>
|
@xvaara @dwgray I'm not sure if this behavior is wanted. Originally when I implemented this functionality I thought it would be wanted to close details if you did something like switch pages in certain contexts. By adding primary key support here, this stuff would stay open in certain contexts. I'm just not sure the best UX if they should close again or not. The situation is if object references change. |
|
When thinking about it, this is after all the intended purpose of the primary key. To persist data... But it leaves issues with the current implementation of WeakMap. I think it may need to dynamically choose between weakmap and map since strings don't fulfill the constraints of weakmap |
| // Fall back to object reference | ||
| return [item, item._showDetails] | ||
| } | ||
| const detailsMap = ref(new Map<object | string, boolean | undefined>()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot we still want to use a WeakMap when primary key is not defined because we don't want to hold around unnecessary resources when possible. We should likely make it a Map when primary key is defined, and weakmap when not.
In addition to that, you also have to be careful of when primary key changes. When it changes, or perhaps goes to undefined, then it should wipe out the map, and/or convert from Map to WeakMap and visa versa.
This switching behavior should also be tested. One can do it I would think by switching the primary key, and then back, should result in the loss of the value in the map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the implementation in commit 77bf95b:
- Now uses
WeakMapwhenprimaryKeyis not defined (for memory efficiency and automatic garbage collection) - Uses
MapwhenprimaryKeyis defined (to support string keys) - Added watcher for
primaryKeyprop changes that clears and recreates the map with the appropriate type - Added helper functions for type-safe map operations (
hasDetailsValue,setDetailsValueByKey, etc.) - Added comprehensive tests for the switching behavior:
- Clears details when primaryKey changes to a different field
- Clears details when primaryKey is removed (set to undefined)
- Clears details when primaryKey is changed and then changed back
All 1635 tests passing.
…iency - Changed to dynamically use WeakMap when no primaryKey (memory efficient) and Map when primaryKey is defined - Added watcher to recreate map when primaryKey prop changes - Added helper functions for type-safe map operations - Added tests for primaryKey switching behavior to verify map is cleared when primaryKey changes - All 1635 tests passing Co-authored-by: VividLemon <[email protected]>
Added comprehensive documentation section explaining: - How primary key affects row details persistence - Behavior with and without primary key prop - Example usage with code snippets - Important notes about primary key changes and uniqueness Co-authored-by: VividLemon <[email protected]>
|
@copilot The documentation doesn't need to be that robust. Meerly a note about how primary key will effect row details and allow persistence even when the object is disposed, or it is a new object entirely. We don't need an example here, but note that it is a weakmap when no primary key is set, and if the objects are collected by memory, then it is destroyed from the map |
Reduced documentation to a single note explaining: - Primary key enables row details persistence with new object references - WeakMap usage without primary key for memory efficiency - Garbage collection behavior Removed code examples and detailed sections per feedback. Co-authored-by: VividLemon <[email protected]>
Simplified the documentation in commit 89b6c9f to a concise note that explains:
Removed all code examples and detailed sections. |
commit: |
* upstream/main: (28 commits) fix(BToggle)! Remove redundant attribute cleanup & update docs for accessibility attributes on show/hide components (bootstrap-vue-next#2918) chore: release main (bootstrap-vue-next#2912) fix: allow custom component props in orchestrator create methods with type safety (bootstrap-vue-next#2922) fix(BModal): prevent focus trap error when no tabbable elements exist (bootstrap-vue-next#2864) Update package description for clarity (bootstrap-vue-next#2917) Update project description for clarity and detail test: add event emission tests for BTable and BTableLite (bootstrap-vue-next#2915) fix(BTableLite): Use primary key to persist row-details state when items change (bootstrap-vue-next#2871) chore: release main (bootstrap-vue-next#2896) feat(BTable): add configurable debouncing ci: Add publint to the build process (bootstrap-vue-next#2909) docs(Offcanvas): Parity pass (bootstrap-vue-next#2900) fix(directives): Robustness fixes for directives (bootstrap-vue-next#2906) docs(BFormInput): document @wheel.prevent for disabling mousewheel events (bootstrap-vue-next#2903) fix(typings): Fix paths to `*.d.mts` files (bootstrap-vue-next#2907) feat: add name and form props to BFormRating for form submission (bootstrap-vue-next#2895) docs: refactor docs to avoid duplication and boilerplate code (bootstrap-vue-next#2891) docs(BToast): Parity (bootstrap-vue-next#2887) docs(BModal): fix attribute to hide footer (bootstrap-vue-next#2888) docs(BPlaceholder): Parity pass (bootstrap-vue-next#2886) ...
Fix: BTable row-details get hidden on "Load more"
Fixes row-details being hidden when items array is updated with new object references.
Problem
When using BTable/BTableLite with row-details, if the items array is replaced with new objects (even with the same data), the row-details would be hidden. This commonly happens in "Load more" scenarios where the entire items array is recreated.
Root Cause: The
detailsMapused aWeakMapwith object references as keys. When items were replaced with new objects, the map lost track of which rows had details open.Solution
Updated BTableLite to dynamically use the appropriate map type and track by primary key when available:
primaryKey- for memory efficiency (garbage collection of unused items)primaryKeyis defined - to support string keys for primary key trackingprimaryKeychanges - recreate the map when the primaryKey prop changesgenerateDetailsItemto return the primary key string whenprimaryKeyprop is provided and the item contains that keyprimaryKeyis provided (maintains full backward compatibility)Usage
To enable row-details persistence across item updates, provide a
primary-keyprop:When items are updated (e.g., in a "Load more" scenario):
Demo
The fix is demonstrated with two tables - one with
primary-keyand one without:primary-key): Alice's details remain open after clicking "Load More" ✅primary-key): Alice's details are closed after clicking "Load More" (expected behavior for backward compatibility)Changes
Core Implementation (
BTableLite.vue):detailsMap: Dynamically initialized asWeakMap(no primaryKey) orMap(with primaryKey)primaryKeyprop changes - clears and recreates map with appropriate typegenerateDetailsItem: Returns primary key string whenprimaryKeyprop is providedhasDetailsValue: Type-safe.has()checksetDetailsValueByKey: Type-safe.set()operationgetDetailsMapKey: Consistent key generationgetDetailsValue: Type-safe.get()for itemssetDetailsValue: Type-safe.set()for itemsDocumentation (
table.md):Tests (
table-lite.spec.ts):Behavior
Memory Efficiency
Using WeakMap when no primaryKey is provided ensures:
Backward Compatibility
✅ Fully backward compatible - when no
primaryKeyis provided, uses WeakMap (memory efficient, original behavior). WhenprimaryKeyis provided, uses Map (supports primary key tracking). This is a progressive enhancement that only activates when theprimary-keyprop is used.Testing
Fixes #2870
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.