Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ux Live Component Laravel Package

symfony/ux-live-component

Build interactive UIs in Symfony with Live Components: stateful Twig components that update via Ajax without writing custom JavaScript. Handle actions, validation, and form binding, with predictable server-side rendering and smooth partial updates.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require symfony/ux-live-component
    

    Ensure symfony/ux-twig-component is also installed (dependency).

  2. Enable Bundle: Add to config/bundles.php:

    return [
        // ...
        Symfony\UX\LiveComponent\LiveComponentBundle::class => ['all' => true],
    ];
    
  3. Basic Component: Create a controller with #[AsLiveComponent]:

    use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
    use Symfony\UX\LiveComponent\Attribute\LiveProp;
    
    #[AsLiveComponent]
    class CounterComponent
    {
        #[LiveProp]
        public int $count = 0;
    
        public function increment(): void
        {
            $this->count++;
        }
    }
    
  4. Template (templates/counter.html.twig):

    <div>
        Count: {{ count }}
        <button data-action="click->increment">+</button>
    </div>
    
  5. Register Route:

    # config/routes.yaml
    _ux_live_component:
        resource: '@LiveComponentBundle/config/routes.php'
        prefix: /_components
    
  6. Use in Parent Template:

    {{ component('app_counter') }}
    

First Use Case

Replace a traditional form submission with real-time updates. For example, a search bar that updates results without page reloads.


Implementation Patterns

Core Workflows

  1. Model Binding:

    • Use #[LiveProp] to bind form inputs to component properties.
    • Example:
      #[LiveProp(writable: ['name', 'email'])]
      public User $user;
      
    • Template:
      <input data-model="name" type="text">
      <input data-model="email" type="email">
      
  2. Actions:

    • Define public methods to trigger logic (e.g., save(), delete()).
    • Bind to DOM events via data-action:
      <button data-action="click->save">Save</button>
      
  3. Child Components:

    • Nest components by including them in templates:
      {{ component('app_child_component', { prop: value }) }}
      
    • Use acceptUpdatesFromParent: true to propagate parent updates:
      #[LiveProp(acceptUpdatesFromParent: true)]
      public string $prop;
      
  4. Forms:

    • Use ComponentWithFormTrait for seamless form handling:
      use Symfony\UX\LiveComponent\Form\ComponentWithFormTrait;
      
      #[AsLiveComponent]
      class UserFormComponent
      {
          use ComponentWithFormTrait;
      
          public function __construct(private EntityManagerInterface $em) {}
      
          public function handleForm(FormInterface $form): void
          {
              if ($form->isSubmitted() && $form->isValid()) {
                  $this->em->persist($form->getData());
                  $this->em->flush();
              }
          }
      }
      
    • Template:
      {{ form_start(form) }}
          {{ form_row(form.name) }}
          {{ form_row(form.email) }}
          <button type="submit">Submit</button>
      {{ form_end(form) }}
      
  5. Dynamic Templates:

    • Use FromMethod for dynamic template resolution:
      #[AsLiveComponent(template: FromMethod('getTemplate'))]
      class DynamicComponent
      {
          public function getTemplate(): string
          {
              return $this->user->isAdmin() ? 'admin_template.html.twig' : 'user_template.html.twig';
          }
      }
      

Integration Tips

  • Validation: Use ValidatableComponentTrait for form validation:

    use Symfony\UX\LiveComponent\Form\ValidatableComponentTrait;
    
    #[AsLiveComponent]
    class ValidatedComponent
    {
        use ValidatableComponentTrait;
    
        public function handleForm(FormInterface $form): void
        {
            if ($form->isSubmitted() && $this->validate($form)) {
                // Handle valid form
            }
        }
    }
    
  • Events: Emit custom events between components:

    $this->emit('userUpdated', ['id' => $user->id]);
    

    Listen in JavaScript:

    component.on('userUpdated', (event) => {
        console.log(event.detail);
    });
    
  • Stimulus Integration: Combine with Stimulus for hybrid approaches:

    {{ component('app_component', { controller: 'my-stimulus-controller' }) }}
    
  • Testing: Use InteractsWithLiveComponents for component tests:

    use Symfony\UX\LiveComponent\Test\InteractsWithLiveComponents;
    
    class CounterComponentTest extends TestCase
    {
        use InteractsWithLiveComponents;
    
        public function testIncrement(): void
        {
            $component = $this->createLiveComponent(CounterComponent::class);
            $rendered = $component->render();
            $this->assertSelectorTextContains('div', 'Count: 0');
    
            $component->increment();
            $this->assertSelectorTextContains('div', 'Count: 1');
        }
    }
    

Gotchas and Tips

Pitfalls

  1. CSRF and CORS:

    • Ensure fetchCredentials is configured for cross-origin requests:
      #[AsLiveComponent(fetchCredentials: 'include')]
      class MyComponent {}
      
    • Global config in config/packages/live_component.yaml:
      live_component:
          fetch_credentials: 'include'
      
  2. Model Updates vs. Actions:

    • Model updates (data-model) and actions (data-action) are not atomic. Use norender to avoid unintended re-renders:
      <input data-model="norender|count">
      
  3. Child Component Re-renders:

    • Parent updates do not automatically re-render children. Explicitly opt-in:
      #[LiveProp(acceptUpdatesFromParent: true)]
      public string $prop;
      
  4. Form Handling:

    • Remove data-action="live#update" from forms. Use data-model="on(change)|*" instead:
      <form data-model="on(change)|*">
          <input name="field">
      </form>
      
  5. Type Mismatches:

    • LiveComponent handles type mismatches gracefully (e.g., string → int), but validate early to avoid silent failures.
  6. SVG and Dynamic Content:

    • Ensure data-live-id is set for dynamic content (e.g., SVGs) to maintain DOM structure during updates.
  7. Debugging:

    • Use the debug:live-component command to inspect component state:
      php bin/console debug:live-component
      
    • Enable JavaScript error modals for debugging:
      // In your Stimulus controller
      this.component.on('response:error', (event) => {
          console.error(event.detail);
      });
      

Tips

  1. Performance:

    • Use #[LiveProp(useSerializerForHydration: false)] for complex objects to avoid serialization overhead.
    • Leverage min_length, max_length, etc., modifiers to reduce unnecessary updates:
      <input data-model="min_length(3)|search">
      
  2. Loading States:

    • Use data-loading for visual feedback:
      <span data-loading="action(save)|show">Loading...</span>
      
  3. Component Isolation:

    • Prefix component IDs to avoid conflicts:
      {{ component('app_my_component', { id: 'unique-' ~ id }) }}
      
  4. Mercure Integration:

    • Combine with Mercure for server-sent updates:
      $this->emit('userUpdated', ['id' => $user->id]);
      // Subscribe via Mercure hub
      
  5. Asset Mapping:

    • Use symfony/asset-mapper for dynamic asset paths:
      #[LiveProp]
      public string $imagePath = $this->assetMapper->getUrl('images/default.png');
      
  6. TypeScript:

    • Extend the Component type for custom logic:
      interface MyComponent extends Component {
          increment(): void;
      }
      
  7. Fallbacks:

    • Provide fallback templates for edge cases:
      #[AsLiveComponent(template: FromMethod('getTemplate'))]
      public function getTemplate(): string
      {
          return $this->user ? 'user_template.html.twig' : 'guest_template.html.twig';
      }
      
  8. Browser Events:

    • Dispatch custom browser events for frontend reactivity:
      $this->dispatchBrowserEvent('custom:event', ['data' => 'value']);
      
    • Listen in JavaScript:
      document.addEventListener('
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime