Found an elegant way of doing it without displaying every error that $this->validate() triggers:
(I'm using constants from a ButtonState class, DISABLED = 0, ENABLED = 1, LOADING = 2, ymmv)
public int $buttonState;
public function mount(Property $property): void
{
$this->buttonState = ButtonState::STATE_DISABLED;
}
public function updated($propertyName)
{
$this->validateOnly($propertyName);
try {
// Validate in a try/catch block to intercept the validation error.
$this->validate();
// If no exception was thrown, the form is valid, so we enable the button.
$this->buttonState = ButtonState::STATE_ENABLED;
} catch (ValidationException $e) {
// If the global validation failed, keep the button disabled.
$this->buttonState = ButtonState::STATE_DISABLED;
}
}
public function submit(): void
{
$data = $this->validate();
$this->buttonState = ButtonState::STATE_LOADING;
// Submit the form, then you probably want to enable it again.
$this->buttonState = ButtonState::STATE_ENABLED;
}
Then in your Blade template:
<button
type="submit"
class="btn {{ $buttonState === \App\Constants\ButtonState::STATE_LOADING ? 'is-loading' : '' }}
{{ $buttonState === \App\Constants\ButtonState::STATE_DISABLED ? 'disabled' : '' }}
>
{{ __('Submit') }}
</button>