Documentation

Livewire Components

Livewire Components

Overview

UltraViolet Pro includes 9 production-ready Livewire components that demonstrate best practices and real-world functionality. Each component is fully functional, well-documented, and ready to use or customize.

Component Library

1. Counter Component

Location: app/Livewire/Counter.php
View: resources/views/livewire/counter.blade.php
Route: /livewire/components/counter

A simple counter that demonstrates the basics of Livewire.

Features:

  • Increment/decrement buttons
  • Reset functionality
  • Real-time state management
  • Clean, minimal design

Usage:

<livewire:counter />

Code Example:

<?php
namespace App\Livewire;

use Livewire\Component;

class Counter extends Component
{
    public $count = 0;

    public function increment()
    {
        $this->count++;
    }

    public function decrement()
    {
        $this->count--;
    }

    public function render()
    {
        return view('livewire.counter');
    }
}

2. Mini Counter

Location: app/Livewire/MiniCounter.php
View: resources/views/livewire/mini-counter.blade.php
Route: Embedded in /livewire/dashboard

A compact counter widget perfect for dashboards and sidebars.

Features:

  • Compact design
  • Multiple increment options (1, 5, 10)
  • Reset button
  • Card-based layout

Usage:

<livewire:mini-counter />

Perfect For:

  • Dashboard widgets
  • Sidebar components
  • Quick counters in small spaces

3. Todo List

Location: app/Livewire/Todo.php
View: resources/views/livewire/components/todo.blade.php
Route: /livewire/components/todo

Full-featured task management component.

Features:

  • Add new tasks
  • Mark tasks as complete/incomplete
  • Delete tasks
  • Task filtering (all, active, completed)
  • Empty state handling
  • Form validation

Usage:

<livewire:todo />

Key Methods:

public function addTodo()      // Add new task
public function toggle($id)    // Toggle completion
public function delete($id)    // Delete task

Great For:

  • Project management
  • Personal task lists
  • Team collaboration tools

4. Quick Todo

Location: app/Livewire/QuickTodo.php
View: resources/views/livewire/quick-todo.blade.php
Route: Embedded in /livewire/dashboard

Streamlined todo widget for quick task management.

Features:

  • Compact interface
  • Inline task addition
  • One-click toggle
  • Delete on hover
  • Pre-seeded with examples

Usage:

<livewire:quick-todo />

Differences from Full Todo:

  • Simplified UI
  • No filtering options
  • Designed for dashboard use
  • Minimal visual footprint

5. Contact Form

Location: app/Livewire/ContactForm.php
View: resources/views/livewire/components/form.blade.php
Route: /livewire/components/form

Professional contact form with validation.

Features:

  • Real-time validation
  • Error messages
  • Success feedback
  • Email input with validation
  • Message textarea
  • Bootstrap styling

Usage:

<livewire:contact-form />

Validation Rules:

protected $rules = [
    'name' => 'required|min:3',
    'email' => 'required|email',
    'message' => 'required|min:10'
];

Real-Time Validation:

<input wire:model.blur="name">
@error('name') <span class="error">{{ $message }}</span> @enderror

6. Search Component

Location: app/Livewire/Search.php
View: resources/views/livewire/components/search.blade.php
Route: /livewire/components/search

Real-time search with instant results.

Features:

  • Live search as you type
  • Debounced input (300ms)
  • Result highlighting
  • Empty state handling
  • Sorting options
  • Pagination support

Usage:

<livewire:search />

Search Implementation:

public $search = '';

public function render()
{
    $results = User::where('name', 'like', "%{$this->search}%")
                  ->orWhere('email', 'like', "%{$this->search}%")
                  ->limit(10)
                  ->get();

    return view('livewire.search', ['results' => $results]);
}

Wire Modifiers:

<!-- Live (instant) -->
<input wire:model.live="search">

<!-- Debounced -->
<input wire:model.live.debounce.300ms="search">

<!-- On blur -->
<input wire:model.blur="search">

7. Vector Maps

Location: app/Livewire/MapsVector.php
View: resources/views/livewire/maps-vector.blade.php
Route: /livewire/components/vector-maps

Interactive map component with controls.

Features:

  • Multiple map styles (street, satellite, terrain)
  • Layer toggles (traffic, buildings, POI)
  • Zoom controls
  • Reset view button
  • Livewire state management
  • JSVectorMap integration

Usage:

<livewire:maps-vector />

Map Controls:

public function changeMapStyle($style)     // Switch map style
public function toggleTrafficLayer()       // Show/hide traffic
public function toggleBuildingsLayer()     // Show/hide buildings
public function zoomIn()                   // Zoom in
public function zoomOut()                  // Zoom out
public function resetView()                // Reset to default

JavaScript Integration:

@push('scripts')
<script>
    Livewire.on('mapUpdated', (data) => {
        // Update map based on Livewire state
        map.setStyle(data.style);
    });
</script>
@endpush

8. Chirps (Social Media)

Location: app/Livewire/Chirps.php
View: resources/views/livewire/chirps.blade.php
Route: /chirper

Full social media posting component (like Twitter/X).

Features:

  • Create new chirps
  • Edit own chirps
  • Delete own chirps
  • Character counter
  • Timestamp display
  • User authentication
  • Policy-based authorization
  • Real-time updates
  • Demo data integration

Data Requirements:

  • Requires chirps table (created by migration)
  • Uses DemoChirpService for sample data
  • Mixes real database chirps with demo chirps
  • User authentication required for posting

Usage:

<livewire:chirps />

Key Features:

public function store()     // Create chirp
public function edit($id)   // Edit mode
public function update()    // Save changes
public function delete($id) // Delete chirp

Authorization:

// In ChirpPolicy.php
public function update(User $user, Chirp $chirp)
{
    return $chirp->user()->is($user);
}

Character Limit:

<textarea 
    wire:model="message" 
    maxlength="255"
></textarea>
<span>{{ strlen($message) }}/255</span>

9. Stats Widget

Location: app/Livewire/StatsWidget.php
View: resources/views/livewire/stats-widget.blade.php
Route: Embedded in /livewire/dashboard

Live statistics widget with auto-refresh.

Features:

  • Real-time stat updates
  • Auto-refresh (every 5 seconds)
  • Multiple metrics (visitors, sales, revenue)
  • Animated counters
  • Responsive cards

Usage:

<livewire:stats-widget />

Auto-Refresh:

#[On('refresh-stats')]
public function refreshStats()
{
    $this->visitors = rand(100, 500);
    $this->sales = rand(10, 50);
    $this->revenue = rand(1000, 5000);
}

Polling:

<div wire:poll.5s="refreshStats">
    <!-- Stats display -->
</div>

Component Data Requirements

Database Setup Required

Some components require database setup to function properly:

1. Chirps Component

# Run migrations to create chirps table
php artisan migrate

# Seed with sample chirps
php artisan db:seed --class=ChirpSeeder

2. Authentication Components

# Run migrations for users table
php artisan migrate

# Seed with test users
php artisan db:seed --class=UserSeeder

3. All Components Demo Data

# Seed all demo data at once
php artisan db:seed

Component Dependencies

Component Database Required Seeder Required Auth Required
Counter
Mini Counter
Todo List
Quick Todo
Contact Form
Search ✅ Users table UserSeeder
Vector Maps
Chirps ✅ Chirps table ChirpSeeder
Stats Widget

Quick Setup for All Components

# Complete setup for all components
php artisan migrate:fresh --seed

# This will:
# 1. Drop all tables
# 2. Re-run all migrations
# 3. Seed with all demo data
# 4. Create test users
# 5. Create sample chirps

Common Patterns

Wire Directives

wire:model - Two-way data binding

<input wire:model="name">

wire:click - Click events

<button wire:click="save">Save</button>

wire:submit - Form submission

<form wire:submit="submit">

wire:loading - Loading states

<span wire:loading>Saving...</span>

wire:poll - Polling/auto-refresh

<div wire:poll.5s="refresh">

Modifiers

live - Real-time updates

<input wire:model.live="search">

debounce - Delay updates

<input wire:model.live.debounce.500ms="search">

blur - Update on blur

<input wire:model.blur="email">

prevent - Prevent default

<form wire:submit.prevent="save">

Component Communication

Events

Dispatch events:

$this->dispatch('userSaved', userId: $user->id);

Listen for events:

#[On('userSaved')]
public function handleUserSaved($userId)
{
    // Handle event
}

JavaScript listeners:

@push('scripts')
<script>
    Livewire.on('userSaved', (data) => {
        console.log('User saved:', data.userId);
    });
</script>
@endpush

Validation

Real-Time Validation

class ContactForm extends Component
{
    public $email;

    protected $rules = [
        'email' => 'required|email'
    ];

    public function updated($propertyName)
    {
        $this->validateOnly($propertyName);
    }
}

Display Errors

<input wire:model="email">
@error('email') 
    <span class="text-danger">{{ $message }}</span> 
@enderror

File Uploads

use Livewire\WithFileUploads;

class FileUpload extends Component
{
    use WithFileUploads;

    public $photo;

    public function save()
    {
        $this->validate([
            'photo' => 'image|max:1024'
        ]);

        $this->photo->store('photos');
    }
}
<input type="file" wire:model="photo">

@if ($photo)
    <img src="{{ $photo->temporaryUrl() }}">
@endif

<button wire:click="save">Upload</button>

Pagination

use Livewire\WithPagination;

class Users extends Component
{
    use WithPagination;

    public function render()
    {
        return view('livewire.users', [
            'users' => User::paginate(10)
        ]);
    }
}
@foreach($users as $user)
    <div>{{ $user->name }}</div>
@endforeach

{{ $users->links() }}

Performance Tips

1. Use Wire:loading for Feedback

<button wire:click="save">
    <span wire:loading.remove>Save</span>
    <span wire:loading>Saving...</span>
</button>

2. Debounce Search Inputs

<input wire:model.live.debounce.500ms="search">

3. Use wire:key for Lists

@foreach($items as $item)
    <div wire:key="item-{{ $item->id }}">
        {{ $item->name }}
    </div>
@endforeach

4. Lazy Loading

<livewire:stats-widget lazy />

5. Optimize Queries

// Bad
public function render()
{
    return view('livewire.users', [
        'users' => User::all() // Loads all users!
    ]);
}

// Good
public function render()
{
    return view('livewire.users', [
        'users' => User::limit(10)->get()
    ]);
}

Testing

Feature Test Example

use Livewire\Livewire;

test('can increment counter', function () {
    Livewire::test(Counter::class)
        ->assertSet('count', 0)
        ->call('increment')
        ->assertSet('count', 1);
});

Form Test Example

test('validates contact form', function () {
    Livewire::test(ContactForm::class)
        ->set('email', 'invalid-email')
        ->call('submit')
        ->assertHasErrors('email');
});

Next Steps

  • [Layout System]({{ route('docs.show', 'livewire/layout') }}) - Learn about the Livewire layout
  • [Best Practices]({{ route('docs.show', 'livewire/best-practices') }}) - Tips and patterns
  • Livewire Docs - Official documentation

Ready to customize? All component source code is fully editable in app/Livewire/ and resources/views/livewire/. Make them your own! 🎨