Skip to content

/live-component

Symfony UX LiveComponent for reactive server-rendered UI -- components that re-render via AJAX on user interaction, zero JavaScript required. Use when building live search, real-time filtering, dynamic forms, inline validation, dependent selects, auto-save, polling,

shell
$ npx -y skills add smnandre/symfony-ux-skills --skill live-component --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/live-component
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Symfony UX LiveComponent for reactive server-rendered UI -- components that re-render via AJAX on user interaction, zero JavaScript required. Use when building live search, real-time filtering, dynamic forms, inline validation, dependent selects, auto-save, polling,

SKILL.md

live-component.SKILL.md
name: live-component
description: 'Symfony UX LiveComponent for reactive server-rendered UI -- components that re-render via AJAX on user interaction, zero JavaScript required. Use when building live search, real-time filtering, dynamic forms, inline validation, dependent selects, auto-save, polling, deferred/lazy rendering, or any UI that updates itself based on user input. Code triggers: AsLiveComponent, LiveProp, LiveAction, data-model, data-loading, data-live-action-url, ComponentWithFormTrait, LiveListener, emit, defer, lazy, polling. Also trigger when the user asks "how to build a search that filters as I type", "how to validate a form in real-time", "how to make a reactive component in PHP", "how to build dependent selects", "how to defer component rendering", "how to communicate between components via emit", "how to bind a form to a LiveComponent". Do NOT trigger for static reusable UI without reactivity (use twig-component), pure client-side JS behavior (use stimulus), or page-level navigation (use turbo).'
license: MIT
metadata:
  author: Simon Andre
  email: smn.andre@gmail.com
  url: https://smnandre.dev
  version: "1.2.0"

LiveComponent

TwigComponents that re-render dynamically via AJAX. Build reactive UIs in PHP + Twig with zero JavaScript. Every user interaction triggers a server round-trip that re-renders the component and morphs the DOM.

When to Use LiveComponent

Use LiveComponent when a component's output depends on user interaction -- search results that update as you type, forms with real-time validation, filters that refine a list, anything where the UI needs to change based on user input and that change requires server-side data or logic.

If the component never re-renders after initial load, use TwigComponent instead (less overhead, no AJAX). If the interaction is purely client-side (toggle, animation), use Stimulus instead.

Installation

composer require symfony/ux-live-component

Quick Reference

#[AsLiveComponent]           Make component live (re-renderable via AJAX)
#[LiveProp]                  State that persists across re-renders
#[LiveProp(writable: true)]  State that the frontend can modify
#[LiveAction]                Server method callable from frontend
data-model="prop"            Two-way bind input to LiveProp
data-action="live#action"    Call LiveAction on event
data-loading="..."           Show/hide/style elements during AJAX
{{ attributes }}             REQUIRED on root element (wires the Stimulus controller)

Basic Example

// src/Twig/Components/Counter.php
namespace App\Twig\Components;

use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\DefaultActionTrait;

#[AsLiveComponent]
final class Counter
{
    use DefaultActionTrait;

    #[LiveProp]
    public int $count = 0;

    #[LiveAction]
    public function increment(): void
    {
        $this->count++;
    }

    #[LiveAction]
    public function decrement(): void
    {
        $this->count--;
    }
}
{# templates/components/Counter.html.twig #}
<div {{ attributes }}>
    <button data-action="live#action" data-live-action-param="decrement">-</button>
    <span>{{ count }}</span>
    <button data-action="live#action" data-live-action-param="increment">+</button>
</div>

**Critical:** The root element must render `{{ attributes }}`. This injects the Stimulus `data-controller="live"` attribute that makes the whole system work. Without it, nothing re-renders.

LiveProp

State that persists between AJAX re-renders. Props are serialized to the frontend and sent back on every request.

Basic Props

#[LiveProp]
public string $query = '';

#[LiveProp]
public int $page = 1;

#[LiveProp]
public ?User $user = null;  // Entities auto-hydrate by ID

Writable Props (Two-way Binding)

Only writable props can be modified from the frontend via `data-model`:

#[LiveProp(writable: true)]
public string $search = '';

// Writable with specific fields for objects
#[LiveProp(writable: ['email', 'name'])]
public User $user;

URL Binding

Sync a prop to a URL query parameter -- enables bookmarkable/shareable state:

#[LiveProp(writable: true, url: true)]
public string $query = '';
// URL becomes: ?query=search+term

// Custom parameter name
use Symfony\UX\LiveComponent\Metadata\UrlMapping;

#[LiveProp(writable: true, url: new UrlMapping(as: 'q'))]
public string $query = '';
// URL becomes: ?q=search+term

Hydration

Doctrine entities auto-hydrate by ID. For custom types:

#[LiveProp(hydrateWith: 'hydrateStatus', dehydrateWith: 'dehydrateStatus')]
public Status $status;

public function hydrateStatus(string $value): Status
{
    return Status::from($value);
}

public function dehydrateStatus(Status $status): string
{
    return $status->value;
}

Data Binding (data-model)

Bind inputs to writable LiveProps. When the input changes, the component re-renders with the new value.

{# Re-render on change (default) #}
<input type="text" data-model="search">

{# Debounced -- wait 300ms after last keystroke #}
<input type="text" data-model="debounce(300)|search">

{# Only update on blur #}
<input type="text" data-model="on(blur)|search">

{# Update model but don't re-render yet #}
<input type="text" data-model="norender|search">

{# Checkbox, radio, select #}
<input type="checkbox" data-model="enabled">
<select data-model="category">
    <option value="1">Category 1</option>
</select>

Validation Modifiers

{# Only re-render when input meets criteria #}
<input data-model="minlength(3)|search">
<input data-model="maxlength(100)|bio">
<input data-model="min(0)|quantity">
<input data-model="max(999)|price">

LiveAction

Server methods callable from the frontend:

#[LiveAction]
public function save(): void
{
    // Called via data-
Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withsymfony-ux-skills

AI agent skills for the Symfony UX frontend stack -- Stimulus, Turbo, TwigComponent, LiveComponent, UX Icons and UX Map. By Simon Andre

Get the whole plugin, auto-invoked
Stats
165
Stars
0
Views
12
Forks
Maintained
Maintenance
MIT
License
1mo ago
Last commit
5mo ago
Created

Repo: smnandre/symfony-ux-skills

Other skills on symfony-ux-skills.