Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Livewire Form Keeper Laravel Package

mrbohem/livewire-form-keeper

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation: Add the package via Composer:
    composer require mrbohem/livewire-form-keeper
    
  2. Blade Directive: Include the script tag in your layout file (just before </body>):
    <x-livewire-form-keeper::script />
    
  3. First Use Case: Apply the FormKeeper trait to your Livewire component:
    use MrBohem\LivewireFormKeeper\FormKeeper;
    
    class MyForm extends Component
    {
        use FormKeeper;
    
        // Your form properties here
    }
    
    • The package will now automatically persist form data across page transitions (e.g., when navigating away and returning).

Implementation Patterns

Core Workflow

  1. Component Integration:

    • Add the FormKeeper trait to any Livewire component managing form data.
    • No additional configuration is required for basic usage.
  2. Form Field Handling:

    • The package automatically tracks all public properties of the component.
    • Example:
      public $name = '';
      public $email = '';
      
    • These values will persist even if the user navigates away (e.g., to a modal or another page) and returns.
  3. Explicit Control:

    • Whitelist Properties: Use the formKeeperProperties array to specify which properties to persist:
      protected $formKeeperProperties = ['name', 'email']; // Only these will be kept
      
    • Blacklist Properties: Exclude properties from persistence:
      protected $formKeeperExclude = ['password', 'tempField'];
      
  4. Manual Persistence:

    • Trigger persistence manually (e.g., before navigation):
      public function saveFormState()
      {
          $this->persistFormState();
      }
      
    • Useful for custom logic (e.g., debouncing or conditional persistence).
  5. Integration with Navigation:

    • Pair with Livewire's wire:navigate or Alpine.js for seamless transitions:
      <button wire:navigate="{{ route('other.page') }}" @click="persistFormState">
          Go to Next Page
      </button>
      
  6. Multi-Step Forms:

    • Use FormKeeper across multiple components in a multi-step workflow:
      // Step 1 Component
      public $step1Data = [];
      use FormKeeper;
      
      // Step 2 Component
      public $step2Data = [];
      use FormKeeper;
      
    • Data will persist independently for each component.

Advanced Patterns

  1. Custom Storage Backend:

    • Override the default storage mechanism (e.g., for server-side persistence):
      public function getFormKeeperStorage()
      {
          return session()->get('form_keeper_data', []);
      }
      
  2. TTL (Time-to-Live):

    • Implement automatic expiration for stored data:
      public function getFormKeeperTTL()
      {
          return 3600; // 1 hour in seconds
      }
      
  3. Event-Based Persistence:

    • Listen to Livewire events to trigger persistence:
      protected $listeners = ['formStateSaved' => 'handleFormStateSaved'];
      
      public function handleFormStateSaved()
      {
          // Custom logic after persistence
      }
      
  4. Conditional Persistence:

    • Dynamically enable/disable persistence based on component state:
      public function shouldPersistFormState()
      {
          return $this->isFormValid();
      }
      

Gotchas and Tips

Pitfalls

  1. Session Dependency:

    • FormKeeper relies on the browser's sessionStorage by default. Ensure users aren’t in private/incognito mode where sessionStorage may behave unexpectedly.
    • Fix: Use localStorage for broader compatibility (customize via the package’s config or override storage backend).
  2. Property Naming Conflicts:

    • Avoid naming properties formKeeperProperties or formKeeperExclude unless intentional, as they override the package’s defaults.
    • Tip: Use underscores or prefixes (e.g., _formKeeperProperties).
  3. Large Forms:

    • Persisting large datasets (e.g., arrays with thousands of items) may bloat sessionStorage or cause serialization issues.
    • Tip: Use formKeeperExclude to omit non-critical data or implement client-side compression.
  4. Livewire Hydration:

    • If using wire:model.live, rapid updates may trigger unnecessary persistence. Debounce or throttle updates:
      <input wire:model.debounce.500ms="name">
      
  5. Multi-Tab Scenarios:

    • sessionStorage is tab-isolated. Data won’t sync across tabs by default.
    • Tip: Use localStorage for cross-tab persistence or implement a server-side sync layer.
  6. CSRF Token Issues:

    • If forms include CSRF tokens, ensure they’re regenerated after persistence to avoid validation errors.
    • Tip: Exclude CSRF tokens from formKeeperProperties or reset them post-persistence.

Debugging Tips

  1. Inspect Storage:

    • Check what’s being persisted in the browser’s DevTools (Application > sessionStorage or localStorage).
    • Look for the key livewire-form-keeper-{component-hash}.
  2. Log Persisted Data:

    • Add a temporary method to dump persisted data:
      public function debugFormKeeper()
      {
          dd($this->getFormKeeperStorage());
      }
      
  3. Clear Storage Manually:

    • Test persistence by clearing storage and reloading:
      // Run in browser console
      sessionStorage.clear();
      
  4. Check for Overrides:

    • Ensure no other packages or custom code are interfering with sessionStorage or Livewire’s hydration.

Extension Points

  1. Custom Storage Key:

    • Override the storage key format:
      public function getFormKeeperKey()
      {
          return 'custom-form-keeper-' . $this->getId();
      }
      
  2. Serialization Control:

    • Customize how properties are serialized/deserialized:
      protected function serializeFormKeeperData($data)
      {
          return json_encode($data, JSON_UNESCAPED_UNICODE);
      }
      
      protected function deserializeFormKeeperData($data)
      {
          return json_decode($data, true);
      }
      
  3. Event Hooks:

    • Extend the package’s lifecycle with hooks:
      public function beforePersistFormState()
      {
          // Pre-persistence logic
      }
      
      public function afterRestoreFormState()
      {
          // Post-restoration logic
      }
      
  4. Conditional Restoration:

    • Skip restoration under certain conditions:
      public function shouldRestoreFormState()
      {
          return !$this->isFreshInstall() && auth()->check();
      }
      
  5. Fallback to Defaults:

    • Provide default values if persisted data is corrupted:
      public function getFormKeeperDefaults()
      {
          return [
              'name' => 'Default Name',
              'email' => 'default@example.com',
          ];
      }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours