<?php
namespace App\Http\Livewire;
use App\Models\Post;
use Livewire\Component;
use Livewire\WithFileUploads;
class CreatePost extends Component
{
use WithFileUploads;
public $title = '';
public $body = '';
public $tags = [];
public $image;
protected $rules = [
'title' => 'required|min:5|max:255',
'body' => 'required|min:100',
'tags' => 'array|max:5',
'image' => 'nullable|image|max:2048',
];
public function updated($propertyName)
{
// Validate on property update
$this->validateOnly($propertyName);
}
public function save()
{
$validated = $this->validate();
$post = auth()->user()->posts()->create([
'title' => $validated['title'],
'body' => $validated['body'],
]);
if ($this->image) {
$post->addMedia($this->image->getRealPath())
->toMediaCollection('featured');
}
$post->tags()->sync($validated['tags']);
session()->flash('message', 'Post created successfully!');
return redirect()->route('posts.show', $post);
}
public function render()
{
return view('livewire.create-post');
}
}
<div>
@if (session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
@endif
<form wire:submit.prevent="save">
<div>
<label>Title</label>
<input type="text" wire:model.lazy="title">
@error('title') <span class="error">{{ $message }}</span> @enderror
</div>
<div>
<label>Body</label>
<textarea wire:model.debounce.500ms="body"></textarea>
@error('body') <span class="error">{{ $message }}</span> @enderror
<p>{{ strlen($body) }} characters</p>
</div>
<div>
<label>Tags</label>
<select wire:model="tags" multiple>
@foreach($availableTags as $tag)
<option value="{{ $tag->id }}">{{ $tag->name }}</option>
@endforeach
</select>
</div>
<div>
<label>Featured Image</label>
<input type="file" wire:model="image">
<div wire:loading wire:target="image">Uploading...</div>
@if ($image)
<img src="{{ $image->temporaryUrl() }}" width="200">
@endif
</div>
<button type="submit" wire:loading.attr="disabled">
<span wire:loading.remove>Save Post</span>
<span wire:loading>Saving...</span>
</button>
</form>
</div>
Livewire enables reactive, dynamic interfaces without writing JavaScript—components re-render automatically when properties change. I create Livewire components as PHP classes with public properties and methods. Properties bind to Blade views with wire:model, updating in real-time. Actions trigger via wire:click, calling component methods. Livewire handles AJAX requests, diffing, and DOM updates automatically. Validation works identically to forms with $rules properties. Lifecycle hooks like mount() and updated() handle initialization and property changes. For performance, I use wire:model.lazy to reduce requests and wire:loading to show loading states. Livewire bridges the SPA experience with server-side rendering simplicity.