Description
When configuring custom selectability on a table using checkIfRecordIsSelectableUsing(), the checkboxes for non-selectable records are correctly disabled in the UI.
However, if a user selects all records on the page and then clicks the banner link to "Select all matching records" (which switches Livewire to track deselected records), the bulk action ends up executing on the non-selectable records as well.
This happens because the backend database query has no awareness of the PHP closure defined in checkIfRecordIsSelectableUsing().
To prevent this, Filament currently disables deselection tracking entirely when custom selectability is active (canTrackDeselectedRecords() returns false), forcing the client to download all individual IDs. But this workaround causes severe performance issues/memory limits on large datasets, and doesn't actually prevent the backend from resolving non-selectable records if deselection tracking is somehow active or simulated.
Reproduction Repository
https://github.com/hamdyelbatal122/filament-reproduction-20050
Steps to Reproduce
-
Clone the reproduction repository and install dependencies:
-
Setup database, migrations, and seed the demo data:
-
Start the server:
-
Log in at http://127.0.0.1:8000/login with:
- Email:
admin@filamentphp.com
- Password:
password
-
Navigate to the posts page: http://127.0.0.1:8000/blog/posts
-
Notice that the checkbox for "Draft" posts is disabled (configured using checkIfRecordIsSelectableUsing in PostsTable.php).
-
Check the master checkbox in the header to select all posts on the page, then click the banner link "Select all 83 posts matching...".
-
Click the bulk actions dropdown and trigger the "Test Select All" action.
-
You will see an notification saying:
Executed on 101 records. Drafts included: 18
(This shows that the bulk action executed on all records, including the 18 draft posts that are non-selectable).
Description
When configuring custom selectability on a table using
checkIfRecordIsSelectableUsing(), the checkboxes for non-selectable records are correctly disabled in the UI.However, if a user selects all records on the page and then clicks the banner link to "Select all matching records" (which switches Livewire to track deselected records), the bulk action ends up executing on the non-selectable records as well.
This happens because the backend database query has no awareness of the PHP closure defined in
checkIfRecordIsSelectableUsing().To prevent this, Filament currently disables deselection tracking entirely when custom selectability is active (
canTrackDeselectedRecords()returnsfalse), forcing the client to download all individual IDs. But this workaround causes severe performance issues/memory limits on large datasets, and doesn't actually prevent the backend from resolving non-selectable records if deselection tracking is somehow active or simulated.Reproduction Repository
https://github.com/hamdyelbatal122/filament-reproduction-20050
Steps to Reproduce
Clone the reproduction repository and install dependencies:
Setup database, migrations, and seed the demo data:
Start the server:
Log in at
http://127.0.0.1:8000/loginwith:admin@filamentphp.compasswordNavigate to the posts page:
http://127.0.0.1:8000/blog/postsNotice that the checkbox for "Draft" posts is disabled (configured using
checkIfRecordIsSelectableUsinginPostsTable.php).Check the master checkbox in the header to select all posts on the page, then click the banner link "Select all 83 posts matching...".
Click the bulk actions dropdown and trigger the "Test Select All" action.
You will see an notification saying:
(This shows that the bulk action executed on all records, including the 18 draft posts that are non-selectable).