Livewire : wire:model.live et mises à jour en temps réel
DOG&DEV · 25/01/2025
Livewire : wire:model.live et mises à jour en temps réel
Avec wire:model.live, Livewire met à jour la propriété du composant à chaque changement de l’input (ou après un court debounce par défaut). Cela permet des recherches en direct, une validation au fil de la frappe et des interfaces réactives sans JavaScript personnalisé. Ce guide décrit l’usage, le debounce et un exemple de recherche produits.
Prérequis
- Laravel avec Livewire 3.x
- Composant Livewire et vue Blade
1. wire:model vs wire:model.live
wire:model: synchronisation à la perte de focus (blur) ou à la soumission.wire:model.live: synchronisation pendant la saisie. Chaque modification envoie une requête au serveur (avec debounce par défaut pour limiter les appels).
<input type="text" wire:model.live="searchQuery" />
Dès que searchQuery change, le composant est re-rendu côté serveur et le DOM est mis à jour.
2. Debounce
Par défaut, Livewire debounce d’environ 150 ms : la requête part après que l’utilisateur ait arrêté de taper pendant ce délai. On peut le modifier :
<input type="text" wire:model.live.debounce.300ms="userInput" />
Ici, 300 ms. Cela réduit le nombre de requêtes tout en gardant une UX réactive.
3. Exemple : recherche de produits
Vue :
<div>
<input type="text"
wire:model.live.debounce.200ms="searchTerm"
placeholder="Rechercher des produits…">
<div class="search-results">
@forelse($searchResults as $product)
<div class="product-card">
<img src="{{ $product->image_url }}" alt="{{ $product->name }}">
<h3>{{ $product->name }}</h3>
<p class="price">{{ $product->price }} €</p>
<button wire:click="addToCart({{ $product->id }})">Ajouter au panier</button>
</div>
@empty
@if($searchTerm)
<p>Aucun produit pour « {{ $searchTerm }} ».</p>
@endif
@endforelse
</div>
@if($searchTerm && count($searchResults) > 0)
<div class="search-stats">{{ count($searchResults) }} produit(s) trouvé(s).</div>
@endif
</div>
Composant :
class ProductSearch extends Component
{
public $searchTerm = '';
public $searchResults = [];
public $maxResults = 20;
public function updatedSearchTerm()
{
if (strlen($this->searchTerm) >= 2) {
$this->searchResults = Product::where('name', 'like', '%' . $this->searchTerm . '%')
->orWhere('description', 'like', '%' . $this->searchTerm . '%')
->where('status', 'active')
->limit($this->maxResults)
->get();
} else {
$this->searchResults = [];
}
}
public function addToCart($productId)
{
Cart::add($productId, auth()->id());
$this->dispatch('cart-updated');
}
public function render()
{
return view('livewire.product-search');
}
}
updatedSearchTerm() est appelé automatiquement à chaque mise à jour de $searchTerm (après le debounce). On ne lance la recherche que si strlen >= 2 pour limiter les requêtes et les résultats trop larges.
4. Validation en temps réel
wire:model.live peut être couplé à $this->validate() ou à des règles #[Validate] (Livewire 3). À chaque modification, la validation est réexécutée et les $this->getErrorBag() sont mis à jour, ce qui permet d’afficher les erreurs au fil de la saisie sans soumettre le formulaire.
Dépannage
| Symptôme | Cause possible | Correctif |
|---|---|---|
| Trop de requêtes | Pas de debounce ou délai trop court | Utiliser wire:model.live.debounce.200ms (ou plus) |
| Aucun résultat alors que la BDD en a | updatedSearchTerm non appelé ou logique (strlen, status) |
Vérifier le nom de la propriété (searchTerm ↔ wire:model.live) ; logs dans updatedSearchTerm |
| Performance dégradée | Recherche sur de grosses tables sans index | Index sur name, description ; limiter limit() ; envisager une recherche full-text ou un moteur dédié |
Bonnes pratiques
- Debounce systématique pour les champs de recherche ou les inputs qui déclenchent des requêtes.
- Seuil de caractères (2–3) avant de lancer une recherche coûteuse.
- Limiter le nombre de résultats et paginer si besoin.
Ressources
Cet article s’inscrit dans notre série de guides technique et développement web. Pour un serveur ou une application sur-mesure, contact.