F
Filament3w ago
JanV

Revert ToggleColumn State after failed Validation

Hi there, I have a ToggleColumn in a list view, and I’m facing an issue. I’ve added a validation rule, and based on the validation result, I want the toggle to revert to its previous state if the validation fails. This way, the user won’t be confused by seeing an invalid notification while the toggle state has changed. I know this behavior works in the edit or create record views, but I haven’t found a solution for the list view yet. Any hints or guidance would be greatly appreciated!
6 Replies
Vp
Vp3w ago
can you provide some code, i believe you can use beforeStateUpdated() and revert it
JanV
JanV3w ago
This is the column.
ToggleColumn::make('is_active')
->rules(function (Shop $record, $state, Set $set) {
if ($state === false) {
if ($record->isPrintlounge()) {
return [new CanActivatePrintloungeIntegrationRule(shop: $record)];
}
}
return [];
})`
ToggleColumn::make('is_active')
->rules(function (Shop $record, $state, Set $set) {
if ($state === false) {
if ($record->isPrintlounge()) {
return [new CanActivatePrintloungeIntegrationRule(shop: $record)];
}
}
return [];
})`
I tried beforeStateUpdated() but wanted to use rules(), so the record is not updated if the validation fails. As I understand from the documentation
ToggleColumn::make()
->beforeStateUpdated(function ($record, $state) {
// Runs before the state is saved to the database.
})
->afterStateUpdated(function ($record, $state) {
// Runs after the state is saved to the database.
})
ToggleColumn::make()
->beforeStateUpdated(function ($record, $state) {
// Runs before the state is saved to the database.
})
->afterStateUpdated(function ($record, $state) {
// Runs after the state is saved to the database.
})
` The life cycle hook can manipulate the state before or after the record is saved to the DB. But a re-rendering or state binding isn't possible in the list view. May be I don't see the point, yet. I also tested this
ToggleColumn::make('is_active')
->beforeStateUpdated(function ($record, $state){
$state = false;
$record->is_active = false;
})
ToggleColumn::make('is_active')
->beforeStateUpdated(function ($record, $state){
$state = false;
$record->is_active = false;
})
` Just to see if the hook manipulates the state, but still the record is updated with the user input, instead of my manually assigned value.
Vp
Vp3w ago
This maybe very different from what you try to achieve, but here it goes
Tables\Columns\ToggleColumn::make('recommended')
->beforeStateUpdated(function ($state) {
if ($state && static::recommendCount() >= 15) {
// ... send noti about limit recommended

throw ValidationException::withMessages([]); // this line prevents records updated, you may also use `throw new Halt()`
}
}),
Tables\Columns\ToggleColumn::make('recommended')
->beforeStateUpdated(function ($state) {
if ($state && static::recommendCount() >= 15) {
// ... send noti about limit recommended

throw ValidationException::withMessages([]); // this line prevents records updated, you may also use `throw new Halt()`
}
}),
In my case, if recomCount is 15, then it display noti about limit..
JanV
JanV3w ago
I see, I'll try this approach. Thanks mate! Will give an update here as soon I have progress.
Vp
Vp3w ago
Yes sure, and please try to use throw new Halt() to see whether it prevents or not cause my project is a little old, I don't want to dig any deeper.. 😆
JanV
JanV3w ago
Update: throwing the Halt() exception doesn't work. The ValidationException kept the toggle old state! Thanks @Vp