Back to top with progress scrollbar

Discover Symfony UX’s Twig Components. UI without JS or BS.

By Reuben Walker, 20 August, 2022

Astronaut on an alien planet.


With Symfony UX a PHP class + template = Twig component. Use them to build a highly-interactive UI from the comfort of Twig. No JS and no BS are required.

By the way, if you are not familiar with all the acronyms, UX equals user experience, UI equals user interface, JS equals JavaScript, which is a synonym of BS and equals you know.

We are big fans of componentization at Symfony Station’s parent, Mobile Atom Media. The Atom in our name is inspired by atomic design. It aspires to break design elements into the smallest form possible with the aim of reusability. That sounds similar to a programming component. The S in SOLID programming principles in particular. That’s the single responsibility principle.

And we are especially fans of the various flavors of web components used in user interfaces. They are a fine example of atomic design.

But, we are not fans of JavaScript, especially for UI components. For a review of its clusterfuckiry see our article on Frontend Madness. Thus, we love anything that simplifies or better yet eliminates JS. That’s why we use tools like CSSUI on this Drupal site.

In a Symfony project’s UI, components are handled by a group of tools under the purview of Symfony UX. This article is going to explore it and its components that are related to Twig templates. No JavaScript is required for the later.

If you need a primer on Twig, our article, Twig: The Ultimate Guide to the Premier PHP Templating Language, has you covered. Please read it first.

Before we get into Twig components we first need to understand a little about Symfony UX.

Screenshot of SymfonyUX home page

Symfony UX

Symfony describes Symfony UX as “JavaScript tools you can't live without. They’re a set of PHP and JavaScript packages to solve everyday frontend problems featuring Stimulus and Turbo.”

“Symfony UX is an initiative and set of libraries to seamlessly integrate JavaScript tools into your application. For example, want to render a chart with Chart.js? Use UX Chart.js to build the chart in PHP. The JavaScript is handled for you automatically.

Behind the scenes, the UX packages leverage Stimulus: a small, but powerful library for binding JavaScript functionality to elements on your page.”

Yay abstraction.

How does Symfony UX work?

The short answer is when you install a package (aka Stimulus component) Symfony updates everything automagically.

The long answer according to the documentation is ⬇️.

“When you install a UX PHP package, Symfony Flex will automatically update your package.json file to point to a "virtual package" that lives inside the PHP package.

This gives you a real Node package (e.g. @symfony/ux-chartjs) that, instead of being downloaded, points directly to files that already live in your vendor/ directory.

The Flex recipe will usually also update your assets/controllers.json file to add a new Stimulus controller to your app.”

Finally, your assets/bootstrap.js file - working with the @symfony/stimulus-bridge - package will automatically register:

  • All files in assets/controllers/ as Stimulus controllers;
  • And all controllers described in assets/controllers.json as Stimulus controllers.

The end result: you install a package, and you instantly have a Stimulus controller available!”

Are you new to this and don’t know what a controller is?

The Symfony docs have your back.

“A controller is a PHP function you create that reads information from the Requestobject and creates and returns a Response object. The response could be an HTML page, JSON, XML, a file download, a redirect, a 404 error or anything else. The controller runs whatever arbitrary logic your application needs to render the content of a page.”

So, Symfony UX / Stimulus controllers control your user interface. And you can do so without writing a ton of custom JavaScript via Symfony UX components. They handle the JS for you.

However, you can still write custom JavaScript inside Stimulus Controllers or use third-party components. If that floats your boat.

Screenshot from Stimulus JS home page

Because. Stimulus was created and is used by developers outside of Symfony (specifically Ruby on Rails). Thus, additional tools are available beyond the Symfony UX packages.

In particular according to the docs:

  • stimulus-use: Add composable behaviors to your Stimulus controllers, like debouncing, detecting outside clicks and many other things.
  • stimulus-components: A large number of pre-made Stimulus controllers, like for Copying to clipboard, Sortable, Popover (similar to tooltips) and much more.”

As we just mentioned, you can use code from these third-party tools in your controllers.

The docs ⬇️:

“By default, all of your controllers (i.e. files in assets/controllers/ + controllers in assets/controllers.json) will be downloaded and loaded on every page.

Sometimes you may have a controller that is only used on some pages, or maybe only in your admin area. In that case, you can make the controller "lazy". When a controller is lazy, it is not downloaded on initial page load. Instead, as soon as an element appears on the page matching the controller (e.g. <div data-controller="hello">), the controller - and anything else it imports - will be lazyily-loaded via Ajax.

To make one of your custom controllers lazy, add a special comment on top. }

To make a third-party controller lazy, in assets/controllers.json, set fetch to lazy.”

Explore the Symfony UX docs here.


Screenshot of SymfonyCasts Symfony UX course


SymfonyCasts being the wonderful resource it is, has a course on Symfony UX’s use of Stimulus.

And one on its partner Turbo. As the name implies Turbo helps you speed up your site so it’s on par with SPAs. But that’s another article.

Symfony UX: Stimulus Course

Screenshot of Symfony UX components

Symfony UX Components/Packages

As the image above indicates there are other UI functions in addition to the Twig-related components.

You can explore them all here. And we will cover the non-Twig-related ones in an upcoming article.

Alright, enough about Stimulus JS let’s move on to the Twig-related Symfony UX components.

Twig logo


The Twig-related components we will examine are Twig Components and Live Components.

As you know, having read the linked article at the top, Twig is an OOP-based PHP templating engine used to output variables inside HTML. It makes your site's frontend simpler, cleaner, dryer, and more logical.

And its logo looks more like grass than a twig. But, whatever. If you create a programming language, you get to create its logo.

Using Twig you can create a layout template (ex. base.twig.html) or other layouts (ex. landing-page.twig.html). And these full page layouts can inherit from other templates with smaller layouts and dynamic functionality. Headers, footers, menus, buttons, etc. are examples. Unique pages may inherit the base (ex. about) or not (a blog or landing page), but any page template can inherit single-purpose templates (ex. buttons).

You should use Twig to code in a focused way when working with HTML without having PHP or JavaScript in the same file. You are building what the end user will see and should not execute any business logic or fetch data from your database in your Twig templates.

Screenshot of Twig Component

Twig Components

According to the docs, Symfony UX’s Twig Components

“give you the power to bind an object to a template, making it easier to render and re-use small template "units" - like an "alert", markup for a modal, or a category sidebar.”

As seen in the image above, every component consists of (1) a PHP class and (2) a corresponding Twig template that allows you to render it in your Symfony application.

The beauty of this is that Twig Components can fetch other Symfony Services via auto-wiring.

Also, the docs say, “you should make your components as lazy as possible and store only the information you need on its properties (this also helps if you convert your component to a live component later). This is very similar to the idea of "computed properties" in frameworks like Vue.”

They can be nested and embedded as well.

Explore their documentation here.

I would because it takes you through creating a Twig Component.

Now, let’s examine the power of Live Components.

Screenshot of a Live Component

A quick note, this image displays an example of a live component. It does not display a set of Live Components. The list shows Symfony UX components of which Live Components is one. Got it.

Live Components

Again, according to the docs, Live Components

“work with the Twig Component library to give you the power to automatically update your Twig components on the frontend as users interact with them.”

You are taking a Twig Component, placing it in an Eastern European castle ruin, hitting it with lightning, and bam it’s alive!⚡ Or you’re just making it live, not static.

Symfony notes, Live Components are inspired by Livewire and Phoenix LiveView.

When a user interacts with them they are updated via an Ajax call. No JavaScript is required!

They have LiveProps / Stateful Component Properties and Data Binding similar to React or Vue.

Live Components also have automatic Debouncing and Lazy Updating on "change" of a Field. And you can defer a Re-Render until later.

The docs say, “Live Components require a single "default action" that is used to re-render it. By default, this is an empty __invoke() method and can be added with the DefaultActionTrait. Live Components are actually Symfony controllers so you can add the normal controller attributes/annotations (ie #[Cache]/#[Security]) to either the entire class or just a single action.”

You can also trigger custom actions on your component.

More from docs:

“A component can also help render a Symfony form, either the entire form (useful for automatic validation as you type) or just one or some fields (e.g. a markdown preview for a textareaor dependent form fields.”

You can use actions to change your form via collection types.

Docs again:

“Symfony's CollectionType can be used to embed a collection of embedded forms including allowing the user to dynamically add or remove them. Live Components can accomplish make this all possible while writing zero JavaScript.”

Like Twig Components you can embed and nest Live Components.

You can also skip updating specific elements in your Live Component.

The docs say:

“Sometimes you may have an element inside a component that you do not want to change whenever your component re-renders. For example, some elements managed by third-party JavaScript or a form element that is not bound to a model... where you don't want a re-render to reset the data the user has entered. To handle this, add the data-live-ignore attribute to the element.”

Do you want to learn even more about Live Components?

Screenshot of Live Component demos

You can see some demos here.

And explore their documentation here.

Wrapping it up

Alright, you now know more about Symfony UX and specifically its Twig-related components. Symfony UX is an initiative and set of libraries to seamlessly integrate JavaScript tools into your application. Abstraction, people.

Most importantly non-JS tools like Twig can be used as well. That’s if you are on an anti-JavaScript jihad like we are.

And if you weren’t familiar with it, you also learned about the Twig templating engine. It’s used to output variables inside HTML via layout templates.

The power of adding non-JS interactivity to your user interface via Twig Components and jolting them into Live Components is incredible. It’s a better developer experience, user experience, and better for your site’s performance.

Now, go out and implement this goodness into your Symfony projects with no JS or BS required.

Want to get rid of even more JavaScript? Read our article, Frontend Madness: SPAs, MPAs, PWAs, Decoupled, Hybrid, Monolithic, Libraries, Frameworks! WTF for your PHP backend?

Explore some more

Screenshot of SymfonyCasts Twig course

We highly recommend these SymfonyCast courses.

It’s worth the money, people. Plus, they are even entertaining.

To learn about more advanced options, visit the repository @symfony/stimulus-bridge, the Node package that is responsible for a lot of the magic Stimulus JS brings to Symfony UX.

Happy Twigging Symfonistas!

section separator

Join our list  

* indicates required

Please share