I have a Game object which can be controlled via the GamesResource. Here I have following section with actions and status messages inside my form:
Section::make('Game control')
->schema([
FormsComponentsPlaceholder::make('status')
->label('Current status')
->content(function ($record) {
if (!$record->is_running && !$record->current_round && !$record->is_finished) {
return 'The game has not started yet.';
} elseif ($record->is_finished && !$record->is_running) {
return 'Game finished.';
} else {
return 'Current round: ' . $record->currentRound->sort;
}
}),
FormsComponentsActions::make([
FormsComponentsActionsAction::make('startGame')
->label('Start game')
->button()
->visible(fn($record) => !$record->is_running && !$record->is_finished)
->action(function (Game $record, EditRecord $livewire) {
$record->startGame();
$livewire->refreshFormData(['is_running', 'is_finished', 'current_round']);
}),
FormsComponentsActionsAction::make('startNextRound')
->label('Next Round')
->button()
->visible(fn($record) => $record->is_running && !$record->isLastRound())
->action(function (Game $record, EditRecord $livewire) {
$record->startNextRound();
$livewire->refreshFormData(['is_running', 'is_finished', 'current_round']);
}),
FormsComponentsActionsAction::make('finishGame')
->label('Show results')
->button()
->visible(fn($record) => $record->is_running && $record->isLastRound())
->action(function (Game $record, EditRecord $livewire) {
$record->finishGame();
$livewire->refreshFormData(['is_running', 'is_finished', 'current_round']);
})
]),
])
->visibleOn('edit')
This is part of my Game model:
class Game extends Model {
public function isLastRound() {
return $this->current_round // check if current round is set
&& $this->rounds()->count() === $this->currentRound->sort; // check if current round is the last round
}
public function startGame() {
$this->is_running = true;
$this->current_round = $this->rounds()->orderBy('sort')->first()->id;
$this->save();
}
public function startNextRound() {
$currentRoundSort = $this->rounds()->where('id', $this->current_round)->first()->sort;
$nextRound = $this->rounds()->where('sort', $currentRoundSort + 1)->first();
$this->current_round = $nextRound->id;
$this->save();
}
public function finishGame() {
$this->is_running = false;
$this->is_finished = true;
$this->save();
}
}
Currently everything works (nearly) as desired: The status messages show the correct status, the buttons apply the correct changes to the Game object. But clicking a button, for example “Next round”, needs me to refresh the page manually in order to see the change of status from “Current round: 1” to “Current round: 2”.
How do I achieve an automatic refresh, either of the page, or the section or the whole form?
I stumbled upon EditRecord::refreshFormData(), but couldn’t really make it work properly: Funnily enough, the current solution works for Starting and Finishing the game, but not for Next Round.