# Symfony Live Components và UX 3.0: Ứng Dụng Phản Hồi Không Cần JavaScript Năm 2026 > Symfony Live Components xây dựng giao diện phản hồi bằng PHP và Twig mà không cần JavaScript. Hướng dẫn chi tiết về LiveProp, LiveAction, form và deferred loading. - Published: 2026-05-10 - Updated: 2026-05-10 - Author: SharpSkill - Tags: symfony, live-components, ux-3, php, reactive - Reading time: 8 min --- Symfony Live Components mang đến giao diện người dùng phản hồi và thời gian thực hoàn toàn bằng PHP và Twig. Phát hành vào tháng 4 năm 2026, [Symfony UX 3.0](https://symfony.com/blog/symfony-ux-3-0-0-released) loại bỏ toàn bộ các deprecation từ phiên bản 2.x, nâng yêu cầu tối thiểu lên PHP 8.4 và Symfony 7.4, đồng thời loại bỏ bốn gói lỗi thời — tạo ra bộ công cụ UX gọn nhẹ nhất từ trước đến nay. > **Live Components Là Gì?** > > Live Components biến bất kỳ component Twig nào thành phần tử có trạng thái và tương tác, được render lại phía server khi người dùng tương tác — mà không cần viết JavaScript. Data binding, action, validation và xử lý form đều diễn ra trong PHP. ## Thiết Lập Symfony UX 3.0 Với Live Components Quá trình cài đặt yêu cầu Symfony 7.4+, PHP 8.4+ và AssetMapper hoặc Webpack Encore cho asset frontend. ```bash # terminal composer require symfony/ux-live-component # With AssetMapper (recommended for Symfony 7.4+) php bin/console importmap:require @symfony/ux-live-component # Verify installation php bin/console debug:twig --filter=component ``` AssetMapper xử lý việc phân phối JavaScript mà không cần Node.js, Webpack hay bất kỳ bước build nào. Stimulus controller hỗ trợ Live Components được tải tự động. ## Tạo Component Tìm Kiếm Phản Hồi Với LiveProp Một thanh tìm kiếm lọc kết quả khi người dùng gõ — không cần JavaScript. Thuộc tính `#[LiveProp]` đánh dấu các property là có trạng thái, được duy trì qua các lần re-render thông qua token mã hóa an toàn cho URL. ```php query) < 2) { return []; } return $this->productRepository->search( query: $this->query, category: $this->category === 'all' ? null : $this->category, limit: 20, ); } } ``` Template Twig tương ứng liên kết các input với property bằng `data-model`. ```twig {# templates/components/ProductSearch.html.twig #}
{% for product in this.products %}

{{ product.name }}

{{ product.price|format_currency('EUR') }}
{% else %} {% if query|length >= 2 %}

No results for "{{ query }}".

{% endif %} {% endfor %}
``` Modifier `debounce(300)` chờ 300ms sau lần gõ phím cuối cùng trước khi gửi request. Thuộc tính `key` trên các item danh sách cho phép DOM morphing hiệu quả — chỉ các phần tử thay đổi mới được cập nhật. > **URL Binding Với LiveProp** > > Thiết lập `url: true` trên LiveProp đồng bộ giá trị property với URL trình duyệt dưới dạng query parameter. Kết quả tìm kiếm có thể bookmark và chia sẻ — chỉ với một thuộc tính. ## Xử Lý Hành Động Người Dùng Với LiveAction Ngoài data binding, `#[LiveAction]` phơi bày các phương thức PHP như các action có thể gọi từ frontend. Các đối số được truyền qua `#[LiveArg]`. ```php cartService->add($productId, $quantity); $this->items = $this->cartService->getItems(); // Notify other components on the page $this->emit('cart:updated', [ 'count' => count($this->items), ]); } #[LiveAction] public function removeItem(#[LiveArg] int $itemId): void { $this->cartService->remove($itemId); $this->items = $this->cartService->getItems(); $this->emit('cart:updated', ['count' => count($this->items)]); } public function getTotal(): float { return array_sum(array_map( fn(CartItem $item) => $item->getPrice() * $item->getQuantity(), $this->items, )); } } ``` Template kích hoạt action bằng helper `live_action()` hoặc thuộc tính `data-action`. ```twig {# templates/components/ShoppingCart.html.twig #}

Cart ({{ items|length }})

{% for item in items %}
{{ item.name }} x{{ item.quantity }} {{ (item.price * item.quantity)|format_currency('EUR') }}
{% endfor %}
Total: {{ this.total|format_currency('EUR') }}
``` Phương thức `emit()` phát sóng event đến các Live Components khác trên trang — ví dụ component badge giỏ hàng có thể lắng nghe bằng `#[LiveListener('cart:updated')]` và cập nhật số lượng mà không cần tải lại toàn bộ trang. ## Xác Thực Form Thời Gian Thực Không Cần JavaScript Live Components tích hợp trực tiếp với [Symfony Forms](https://symfony.com/doc/current/forms.html). `ComponentWithFormTrait` kết nối trạng thái form, lỗi validation và submission vào vòng đời component. ```php createForm(RegistrationType::class, $this->initialFormData ?? new User()); } #[LiveAction] public function save(EntityManagerInterface $em): mixed { // Submits + validates — re-renders with errors if invalid $this->submitForm(); $user = $this->getForm()->getData(); $em->persist($user); $em->flush(); $this->addFlash('success', 'Account created.'); return $this->redirectToRoute('app_login'); } } ``` ```twig {# templates/components/RegistrationForm.html.twig #}
{{ form_start(form, { attr: { 'data-action': 'live#action:prevent', 'data-live-action-param': 'save' } }) }} {{ form_row(form.email) }} {{ form_row(form.plainPassword, { label: 'Password' }) }} {{ form_row(form.fullName) }} {{ form_end(form) }}
``` Các lỗi validation xuất hiện inline khi người dùng di chuyển giữa các trường — modifier `on(change)` trên `data-model` kích hoạt re-render khi blur, hiển thị thông báo constraint từ Symfony Validator ngay lập tức. ## Deferred và Lazy Loading Để Tối Ưu Hiệu Suất Các component nặng — dashboard, biểu đồ phân tích, danh sách dài — được hưởng lợi từ deferred rendering. Thay vì chặn việc tải trang ban đầu, component hiển thị placeholder và lấy nội dung qua AJAX sau khi trang đã sẵn sàng. ```php analytics->getMetrics($this->period); } } ``` ```twig {# Parent page: load the dashboard after the page renders #} {# Or load when scrolled into view #} ``` Macro placeholder bên trong template component định nghĩa nội dung người dùng thấy trong khi nội dung thực đang được tải. ```twig {# templates/components/AnalyticsDashboard.html.twig #}

Analytics — {{ period }}

{% for metric in this.metrics %}
{{ metric.label }} {{ metric.value|number_format }}
{% endfor %}
{% macro placeholder(props) %}
{% endmacro %} ``` Chế độ `loading="defer"` gửi request AJAX ngay lập tức khi trang được tải. Chế độ `loading="lazy"` sử dụng IntersectionObserver — request chỉ được gửi khi component cuộn vào viewport. Cả hai cách tiếp cận đều giữ phản hồi trang ban đầu nhanh. > **CSRF Đã Bị Loại Bỏ Trong UX 3.0** > > Symfony UX 3.0 thay thế token CSRF bằng bảo vệ same-origin/CORS cho Live Components. Đối số `csrf` trên `#[AsLiveComponent]` không còn tồn tại. Hãy đảm bảo server thực thi các chính sách same-origin. ## Giao Tiếp Giữa Các Component Bằng Events Live Components giao tiếp thông qua hệ thống event. Component con phát ra event; component cha (hoặc anh em) lắng nghe và phản hồi. ```php count = $cartService->getItemCount(); } // Automatically re-renders when ShoppingCart emits 'cart:updated' #[LiveListener('cart:updated')] public function onCartUpdated(#[LiveArg] int $count): void { $this->count = $count; } } ``` Mẫu thiết kế này giữ các component tách rời nhau. Component ShoppingCart không tham chiếu trực tiếp đến CartBadge — event bus xử lý kết nối. ## Những Thay Đổi Trong Symfony UX 3.0 UX 3.0 là bản phát hành dọn dẹp. Các ứng dụng chạy không có cảnh báo deprecation trên 2.x có thể nâng cấp với ít trở ngại nhất. | Thay đổi | Trước (2.x) | Sau (3.0) | |----------|-------------|------------| | Bảo vệ CSRF | `csrf: true` trên `#[AsLiveComponent]` | Same-origin/CORS (tự động) | | Hàm Twig CVA | `cva()` | `html_cva()` từ twig/html-extra 3.12+ | | Config defaults component | Tùy chọn | `twig_component.defaults` bắt buộc | | Gói bị loại bỏ | Swup, LazyImage, Typed, TogglePassword | Dùng native API hoặc UX Toolkit | | Yêu cầu PHP | 8.1+ | 8.4+ | | Yêu cầu Symfony | 6.4+ | 7.4+ | [UX Toolkit](https://symfony.com/blog/symfonyux-2-32-0-released), được giới thiệu trong chu kỳ 2.x, cung cấp các component UI có sẵn (Button, Dialog, Card, Table, Pagination) được styled với Shadcn UI hoặc Flowbite 4.0 — lấp đầy khoảng trống do các gói bị loại bỏ. Đang chuẩn bị [câu hỏi phỏng vấn Symfony](/technologies/symfony/interview-questions/events-subscribers)? Hiểu biết về Live Components và hệ thống event ngày càng liên quan đến các vị trí cấp cao. [Hướng dẫn câu hỏi phỏng vấn Symfony](/blog/symfony/symfony-interview-questions) bao gồm các chủ đề nền tảng phù hợp để kết hợp với kiến thức thực hành này. ## Kết Luận - Live Components loại bỏ nhu cầu sử dụng framework JavaScript trong hầu hết các ứng dụng Symfony nặng CRUD. Data binding, action, validation và xử lý form đều ở trong PHP và Twig - `#[LiveProp(writable: true, url: true)]` tạo giao diện có trạng thái, có thể bookmark và chia sẻ chỉ với một thuộc tính - Deferred và lazy loading (`loading="defer"` / `loading="lazy"`) giữ tải trang ban đầu nhanh trong khi các component nặng được render bất đồng bộ - UX 3.0 loại bỏ token CSRF để sử dụng bảo vệ same-origin/CORS — bảo mật đơn giản hơn với ít thành phần chuyển động hơn - Hệ thống event (`emit` / `#[LiveListener]`) cho phép giao tiếp component tách rời mà không cần quản lý state toàn cục - Đối với API, kết hợp Live Components với [API Platform trên Symfony 7](/blog/symfony/symfony-7-api-platform-best-practices) cho kiến trúc nặng backend --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/vi/blog/symfony/symfony-live-components-ux-3-reactive-apps-without-javascript