havit / Havit.Blazor

Free Bootstrap 5 components for ASP.NET Blazor + optional enterprise-level stack for Blazor development (gRPC code-first, layered architecture, localization, auth, ...)
https://havit.blazor.eu
MIT License
516 stars 68 forks source link

[HxGrid] Allowing MultiSelectionEnabled with InfiniteScroll navigation (virtualized) #950

Open hakenr opened 3 days ago

hakenr commented 3 days ago

As we implemented the PreserveSelection parameter (#576), it now opens the door to supporting multiselection for InfiniteScroll (virtualized) mode.

There are a few design challenges we need to address:

  1. Dependency on PreserveSelection="true"
    The multiselection feature only makes sense with PreserveSelection="true". Allowing PreserveSelection="false" in virtualized grids with multiselection would create conflicts.

    • Should we enforce PreserveSelection="true" when the feature is used, or should we introduce an automatic default like PreserveSelection="null"? This default would act as "true for InfiniteScroll and false for others."
    • The problem is that null is already used for "cascade inheritance," meaning "not set, use the value from parent settings" (supporting the Defaults-Settings-parameter cascade outlined in Defaults & Settings).
    • To address this, we could introduce a tri-state enum for PreserveSelection, such as:
      • GridPreserveSelection.Enabled
      • GridPreserveSelection.Disabled
      • GridPreserveSelection.Automatic (though this naming might feel odd, since there's no true "automation" in preserving selection - it's just enabled for InfiniteScroll and disabled for other modes).
  2. Handling the "select/deselect all" checkbox
    Virtualization complicates the "select/deselect all" functionality since there’s no clear concept of "visible rows" (due to overscan and other factors, making the feature unpredictable for users). Possible solutions:

    • Quick Win: Hide the "select/deselect all" checkbox in InfiniteScroll mode.
    • Load All Items: Load all items when "select all" is requested. While this would make the feature user-friendly, it could lead to performance issues if not handled carefully.
    • Conditional Display: Show the "select/deselect all" checkbox only when the number of displayed items equals TotalCount, i.e., when all items are effectively displayed regardless of navigation mode.
    • New Bindable Parameter: Introduce a bindable parameter like bool SelectAllChecked, mapping to the checkbox state. Leave the SelectedDataItems collection empty in such a state, allowing developers to implement custom logic (e.g., handling actions on all items without loading them into the grid). However, this approach adds complexity, which might not be desirable.

cc @crdo @jirikanda

hakenr commented 3 days ago

For now, I decided to implement a straightforward solution that leaves room for future enhancements:

  1. Developers will be required to set PreserveSelection="true" when using MultiSelectionEnabled="true" in InfiniteScroll content navigation mode. Setting PreserveSelection="false" in this scenario will throw an exception from OnParametersSet.

  2. The "select/deselect all" checkbox will be hidden in InfiniteScroll mode for now.

    • We can add the only reasonable option - a new bindable SelectAllChecked parameter - later if needed.
    • Developers can still create a custom "Do something with all" button outside the grid, allowing them to programmatically handle all items without assuming all items need to be loaded on the client.
    • Another possible option is a dynamic button: it could switch its behavior between "Do something with all items" and "Do something with selected items" based on whether SelectedDataItems contains any selected items.

This approach is simple, tackles the current challenges, and allows flexibility for future improvements.