<?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.
Related snips
import Combine
import Foundation
class SearchViewModel: ObservableObject {
@Published var searchQuery = ""
@Published var results: [SearchResult] = []
Combine operators for data transformation
<?php
namespace App\Providers;
use App\Contracts\PaymentGateway;
use App\Services\StripePaymentGateway;
Laravel service container and dependency injection
{
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
Laravel mix/Vite for asset compilation
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Laravel database migrations for schema management
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
Laravel form requests for validation
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Laravel soft deletes for data retention
Share this code
Here's the card — post it anywhere.