Skip to main content

Overview

Lyger Livewire provides a server-side reactive component system that allows you to build dynamic interfaces without writing JavaScript. Components automatically handle updates, events, and state management.
Lyger Livewire is inspired by Laravel Livewire but built specifically for the Lyger framework with full integration support.

Creating Components

1

Create Component Class

Extend the Lyger\Livewire\Component base class and implement the render() method:
<?php

namespace App\Livewire;

use Lyger\Livewire\Component;

class Counter extends Component
{
    public int $count = 0;

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

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

    public function render(): string
    {
        return <<<HTML
        <div>
            <h2>Counter: {$this->count}</h2>
            <button wire:click="increment">+</button>
            <button wire:click="decrement">-</button>
        </div>
        HTML;
    }
}
2

Register Component

Register your component with the Livewire manager:
use Lyger\Livewire\Manager;
use App\Livewire\Counter;

Manager::register('counter', Counter::class);
3

Use in Views

Include the component in your views using the component name:
<div id="app">
    @livewire('counter')
</div>

Component Lifecycle

Mount Method

The mount() method is called when a component is first created:
class UserProfile extends Component
{
    public string $name = '';
    public string $email = '';

    public function mount(int $userId): void
    {
        $user = User::find($userId);
        $this->name = $user->name;
        $this->email = $user->email;
    }

    public function render(): string
    {
        return Blade::render('profile.user', [
            'name' => $this->name,
            'email' => $this->email,
        ]);
    }
}

Public Properties

All public properties are automatically tracked and synced with the frontend:
class SearchForm extends Component
{
    public string $query = '';
    public array $results = [];
    public bool $loading = false;

    public function search()
    {
        $this->loading = true;
        $this->results = $this->performSearch($this->query);
        $this->loading = false;
    }

    // Properties are automatically available in the view
    public function render(): string
    {
        return Blade::render('search.form', $this->getPublicProperties());
    }
}

Data Binding

Properties are automatically synchronized between the server and client:
class ContactForm extends Component
{
    public string $name = '';
    public string $email = '';
    public string $message = '';

    public function submit()
    {
        // Validate and process form
        $this->validate([
            'name' => ['required', 'min:3'],
            'email' => ['required', 'email'],
            'message' => ['required', 'min:10'],
        ]);

        // Send email or save to database
        $this->reset('name', 'email', 'message');
    }

    public function render(): string
    {
        return <<<HTML
        <form wire:submit="submit">
            <input type="text" wire:model="name" placeholder="Name">
            <input type="email" wire:model="email" placeholder="Email">
            <textarea wire:model="message" placeholder="Message"></textarea>
            <button type="submit">Send</button>
        </form>
        HTML;
    }
}

Validation

Components include built-in validation support:
class RegistrationForm extends Component
{
    public string $username = '';
    public string $password = '';
    public array $errors = [];

    public function register()
    {
        try {
            $validated = $this->validate([
                'username' => ['required', 'min:3', 'max:20'],
                'password' => ['required', 'min:8'],
            ], [
                'username.required' => 'Username is required',
                'password.min' => 'Password must be at least 8 characters',
            ]);

            // Create user account
            User::create($validated);

            return $this->redirect('/dashboard');
        } catch (ValidationException $e) {
            $this->errors = $e->getErrors();
        }
    }

    public function render(): string
    {
        return Blade::render('auth.register', [
            'username' => $this->username,
            'password' => $this->password,
            'errors' => $this->errors,
        ]);
    }
}

Error Handling

protected function addError(string $field, string $message): void
{
    $this->errors[$field] = $message;
}

Events

Emit events to communicate between components:
class PostCreator extends Component
{
    public string $title = '';
    public string $content = '';

    public function createPost()
    {
        $post = Post::create([
            'title' => $this->title,
            'content' => $this->content,
        ]);

        // Emit event to notify other components
        return $this->emit('postCreated', $post->id);
    }

    public function render(): string
    {
        return Blade::render('posts.create');
    }
}

Component Traits

Lyger Livewire includes reusable traits for common functionality:

WithEvents

use Lyger\Livewire\Component;
use Lyger\Livewire\WithEvents;

class EventDrivenComponent extends Component
{
    use WithEvents;

    protected function mount(): void
    {
        $this->listen('userUpdated', function($userId) {
            $this->refreshUserData($userId);
        });
    }
}

WithFileUploads

use Lyger\Livewire\WithFileUploads;

class FileUploader extends Component
{
    use WithFileUploads;

    public function handleUpload()
    {
        $this->validateFile('document', ['required', 'max:2048']);
        
        $file = $this->request->file('document');
        $path = $this->upload('document', $file);
        
        return $this->redirect("/files?uploaded={$path}");
    }
}

WithPagination

use Lyger\Livewire\WithPagination;

class UserList extends Component
{
    use WithPagination;

    protected int $perPage = 10;

    public function render(): string
    {
        $users = User::paginate($this->perPage, $this->page);
        
        return Blade::render('users.list', [
            'users' => $users,
            'pagination' => $this->pagination(),
        ]);
    }
}

WithSearch

use Lyger\Livewire\WithSearch;

class SearchableTable extends Component
{
    use WithSearch;

    protected array $searchable = ['name', 'email', 'description'];

    public function render(): string
    {
        $query = User::query();
        $results = $this->applySearch($query)->get();
        
        return Blade::render('users.searchable', [
            'results' => $results,
            'search' => $this->search,
        ]);
    }
}

Actions and Methods

Calling Methods

Component methods can be called from the frontend:
class TodoList extends Component
{
    public array $todos = [];

    public function addTodo(string $title)
    {
        $this->todos[] = [
            'id' => uniqid(),
            'title' => $title,
            'completed' => false,
        ];
    }

    public function toggleTodo(string $id)
    {
        foreach ($this->todos as &$todo) {
            if ($todo['id'] === $id) {
                $todo['completed'] = !$todo['completed'];
            }
        }
    }

    public function deleteTodo(string $id)
    {
        $this->todos = array_filter($this->todos, fn($t) => $t['id'] !== $id);
    }
}

Redirects

protected function redirect(string $url): array
{
    return ['redirect' => $url];
}

protected function redirectToRoute(string $route, array $params = []): array
{
    $url = $route;
    foreach ($params as $key => $value) {
        $url = str_replace("{{$key}}", $value, $url);
    }
    return $this->redirect($url);
}
Example usage:
public function saveAndRedirect()
{
    $this->save();
    return $this->redirect('/dashboard');
}

public function viewUser(int $userId)
{
    return $this->redirectToRoute('/users/{id}', ['id' => $userId]);
}

Authentication

Components have built-in authentication helpers:
class ProtectedComponent extends Component
{
    public function mount(): void
    {
        if (!$this->isAuthenticated()) {
            return $this->redirect('/login');
        }
    }

    public function performAction()
    {
        $user = $this->user();
        
        if (!$user) {
            $this->addError('auth', 'You must be logged in');
            return;
        }

        // User data available in $user array
        $userId = $user['id'];
        $userName = $user['name'];
    }
}

Request Handling

The Livewire Manager handles incoming AJAX requests:
use Lyger\Http\Request;
use Lyger\Livewire\Manager;

// In your routes or middleware
$request = Request::capture();

if ($request->isLivewire()) {
    return Manager::handle($request);
}
The Manager automatically handles component instantiation, property updates, and method execution based on the request payload.

Best Practices

1

Keep Components Focused

Each component should have a single responsibility. Break complex UIs into smaller, reusable components.
2

Use Public Properties Wisely

Only make properties public if they need to be tracked and synced. Use protected/private for internal state.
3

Validate User Input

Always validate data before processing, especially for security-sensitive operations.
4

Handle Errors Gracefully

Use try-catch blocks and provide meaningful error messages to users.
5

Optimize Rendering

Cache expensive computations and avoid unnecessary database queries in the render method.

API Reference

Component Methods

MethodDescription
mount(...$params)Called when component is first created
render()Returns the component HTML (required)
getPublicProperties()Gets all public properties as array
callMethod($method, $params)Executes a component method
validate($rules, $messages)Validates component data
addError($field, $message)Adds validation error
reset(...$properties)Resets properties to default
emit($event, ...$params)Emits component event
emitUp($event, ...$params)Emits event to parent
dispatchBrowserEvent($event, $data)Dispatches browser event
redirect($url)Redirects to URL
user()Gets current authenticated user
isAuthenticated()Checks if user is authenticated

Manager Methods

MethodDescription
Manager::register($name, $class)Registers a component
Manager::get($name)Gets component instance
Manager::handle($request)Handles Livewire request