mckenziearts/livewire-unsaved-changes
Installation:
composer require mckenziearts/livewire-unsaved-changes
Publish the config (optional, for customization):
php artisan vendor:publish --provider="McKenzieArts\LivewireUnsavedChanges\ServiceProvider"
Basic Usage: Add the component to your Livewire form view:
<livewire:your-component>
@include('livewire-unsaved-changes::unsaved-changes')
Wrap your form fields in the x-data directive:
<form x-data="unsavedChangesForm">
<!-- Form fields -->
</form>
First Use Case: For a simple form, initialize the component in your Livewire class:
public function mount()
{
$this->unsavedChanges = true; // Enable tracking
}
Form Initialization:
x-data="unsavedChangesForm" on your <form> element to enable tracking.$this->unsavedChanges = true in mount().Dynamic Field Tracking:
x-model with Livewire’s wire:model:
<input x-model="form.dynamicField" wire:model="dynamicField">
Integration with Livewire Events:
unsavedChanges events in your Livewire class:
public function someAction()
{
$this->dispatch('unsaved-changes');
}
Conditional Rendering:
@if($this->shouldShowUnsavedChanges)
@include('livewire-unsaved-changes::unsaved-changes')
@endif
Custom Styling: Override Tailwind classes in your project’s CSS:
.unsaved-changes-bar {
@apply bg-yellow-500 text-white;
}
Multi-Form Pages:
Use unique Alpine x-data namespaces:
<form x-data="unsavedChangesForm1">...</form>
<form x-data="unsavedChangesForm2">...</form>
Server-Side Validation Sync: Reset the unsaved state after validation errors:
protected $rules = [...];
public function updated($property)
{
$this->validateOnly($property);
$this->dispatch('reset-unsaved-changes');
}
Alpine/Livewire Conflicts:
x-data is not nested inside Livewire’s wire:model without proper binding.wire:model.defer for laggy fields to avoid false unsaved triggers.Dynamic Components:
@foreach) may not auto-track changes.unsaved-changes in mount() or updated():
public function mount()
{
$this->dispatch('unsaved-changes');
}
Route Model Binding:
navigating events in Alpine:
<script>
window.addEventListener('navigating', () => {
unsavedChangesForm.reset();
});
</script>
Check Alpine State:
Inspect the unsavedChangesForm object in browser dev tools (console.log(unsavedChangesForm)) to verify tracking.
Disable Auto-Reset:
Temporarily disable auto-reset in config ('auto_reset_on_save' => false) to debug unsaved state persistence.
Event Listeners:
Verify events are firing with Alpine’s x-on:
<div x-on:unsaved-changes="console.log('Change detected!')">
Custom Triggers:
Extend the component to support custom events (e.g., x-on:custom-trigger="unsavedChangesForm.markDirty").
Positioning: Override the default position (top/bottom) via config:
'position' => 'bottom', // or 'top'
Animation Control: Disable animations in config for performance:
'animate' => false,
Localization: Customize the "unsaved changes" text via Alpine:
<script>
unsavedChangesForm.message = 'Cambios sin guardar';
</script>
How can I help you explore Laravel packages today?