Since its creation, JavaScript has always been focused on creating innovative User Experiences. It lets developers create the most intuitive and usable User Experience possible for a specific problem.
In practice however, building great User Experiences with JavaScript is difficult. It takes time to choose reliable packages, to configure them, to integrate them in your pages, and to make your front-end code interact with the rest of your infrastructure.
This problem is not new: it looks a whole lot like the state of Symfony in PHP before Symfony Flex. We need a Symfony Flex equivalent for JavaScript: a tool to build amazing User Experiences as quickly as we can now setup an HTTP client, a Mailer or an administration panel.
That's Symfony UX.
Symfony UX: building highly interactive applications by leveraging JavaScript giants
Symfony UX is a series of tools to create a bridge between Symfony and the JavaScript ecosystem. It stands on the shoulders of JavaScript giants: npm, Webpack Encore and Stimulus.
Symfony UX is not tied to any specific JavaScript framework: you can still use React, Vue or Angular if you love them. It is also opinionated, based on standard HTML and can be progressively adopted in existing applications.
Symfony UX consists of three main components:
- a Symfony integration for Stimulus to provide a new organization for JavaScript code in applications
- updates to Symfony Flex and Symfony Webpack Encore to automatically configure JavaScript code shipped by PHP packages
- a series of core UX packages designed to be reliable and composable to create amazing interfaces quickly
Example: displaying charts in PHP using Symfony UX Chart.js
A good example of the power of Symfony UX is the new Symfony UX Chart.js component. This component relies on the Chart.js library internally.
To use Symfony UX, first update your Symfony Flex and Webpack Encore dependencies:
1 2
composer update symfony/flex
yarn upgrade "@symfony/webpack-encore@^1.0.0"
And synchronize your recipes to the latest version:
1
composer recipes:install symfony/webpack-encore-bundle --force -v
Note
Synchronizing your recipes may override some code of your application. Check manually the result of the command to choose what to keep!
Once updated, Symfony Flex will react to each PHP package you install that contains JavaScript code. For instance, you can now install the Chart.js component:
1
$ composer require symfony/ux-chartjs
1 2 3 4 5 6
Using version ^1.0 for symfony/ux-chartjs
./composer.json has been updated
Synchronizing package.json with PHP packages
Don't forget to run npm or yarn to refresh your Javascript dependencies!
...
Symfony Flex has just synchronized the package.json
file of your project with the
Chart.js PHP package you installed. You will now find in this file a new JavaScript module:
1 2 3 4 5 6 7
// package.json
{
"devDependencies": {
...
"@symfony/ux-chartjs": "file:vendor/symfony/ux-chartjs/Resources/assets"
}
}
Symfony Flex also updated a new assets/controllers.json
file in your project. This file references all the Stimulus controllers provided by installed Symfony UX packages to let Webpack Encore add them to your JavaScript built files:
1 2 3 4 5 6 7 8 9 10 11 12
// assets/controllers.json
{
"controllers": {
"@symfony/ux-chartjs": {
"chart": {
"enabled": true,
"fetch": "eager"
}
}
},
"entrypoints": []
}
Because of these changes, you should now install the new JavaScript dependencies and compile the new files:
1 2
yarn install --force
yarn encore dev
And... that's it! By leveraging Symfony Flex, Symfony UX Chart.js was installed and configured both as a Symfony bundle in PHP, and as a JavaScript library compiled into your application's built files.
This means you can now build a chart using the bundle:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
// ...
use Symfony\UX\Chartjs\Builder\ChartBuilderInterface;
use Symfony\UX\Chartjs\Model\Chart;
class HomeController extends AbstractController
{
/**
* @Route("/", name="homepage")
*/
public function index(ChartBuilderInterface $chartBuilder): Response
{
$chart = $chartBuilder->createChart(Chart::TYPE_LINE);
$chart->setData([
'labels' => ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
'datasets' => [
[
'label' => 'My First dataset',
'backgroundColor' => 'rgb(255, 99, 132)',
'borderColor' => 'rgb(255, 99, 132)',
'data' => [0, 10, 5, 2, 20, 30, 45],
],
],
]);
$chart->setOptions([/* ... */]);
return $this->render('home/index.html.twig', [
'chart' => $chart,
]);
}
}
Once created in PHP, a chart can be displayed using Twig:
1 2 3 4
{{ render_chart(chart) }}
{# You can pass HTML attributes as a second argument to add them on the <canvas> tag #}
{{ render_chart(chart, {'class': 'my-chart'}) }}
All options and data are provided as-is to Chart.js. You can read
Chart.js documentation to discover them all.
Discover all the packages of Symfony UX on github.com/symfony/ux!
You can also read Fabien's keynote slides and Titouan's talk slides to get a full overview on the initiative!
Let's build an amazing ecosystem together
Symfony UX is an initiative: its aim is to build an ecosystem. To achieve this, we need your help: what other packages could we create in Symfony UX? What about a library that automatically adds an input mask to the text fields of your Symfony forms? Or the ability to make the EntityType
render with AJAX auto-completion? Anything you do in JavaScript could be done streamlined as a UX package.
We have some ideas and we will release more packages in the coming days. The rest is on us: let's create an amazing ecosystem together!
Awesome ! Can't wait to see where it can bring Symfony
Thank you!
First issue: https://github.com/symfony/ux/issues/1 :-) An integration of a wysiwyg editor would be great... I think this kind of tools is needed quite often in web applications.
"what other packages could we create in Symfony UX?"
I would like to have Svelte; been playing with it for about 2 weeks and it is absolutely amazing.
The important thing is that components can be easily added to any site with full-page or partial load (swup or dynamic with JS): https://github.com/sveltejs/svelte/issues/5710
This solution works, no problems at all but would still prefer someone with greater JS and Symfony knowledge to take a look; I am sure something is not right or can be improved.
Great initiative!
Excellent work, Awesome initiative. Thank you!
Good job :)
Functionality really interesting and useful. Good Job!!!
Awesome!
I do not mean to be a downer or anything, but is this the right direction to go?
Kind of feels like going against the tide. Would time be better spent on improving Vue / React "compatibility" ?
For example, forms should have the ability to be serialized as a Vue Formulate json schema (https://vueformulate.com/guide/forms/generating-forms/#schemas). That would make adoption much easier for new and existing Symfony projects as well.
Banking on twig, and building js lib funcionality into it feels a bit jury-rigged to me.
I have old and new projects alike, and the server rendered method feels dated, and not fluent enough to compete with SPAs.The simplest things, like 2 selects where the 1st value determines the options of the 2nd select are waaaay better to do with Vue. Just a few weeks ago I had to add this to one of my old projects, and I wished very hard that I had Vue there.
One of the first suggestions was Svelte, a 2 way binding library. No surprise there, these solutions are pretty much expected now.
TLDR: Wouldn't it be better to let dedicated libraries such as React or Vue handle this, and help ease the transition to those libraries ?
@dam Prager compatibility with React and Vue is already provided by API Platform (which has an official Symfony recipe:
composer req api
): https://api-platform.com/docs/client-generator/Symfony UX is not targeting the same kind of projects. If you already know JS and want a modern, JS-heavy UI, an SPA, a Progressive Web App, a native mobile app... then use API Platform with your preferred JS framework.
On the other hand if you don't master a modern JS framework, or just want to progressively enhance the UX of forms built with Twig and the Form Component, then Symfony UX is for you.
Am I the only one who feel doubtful about this ? IMO, it will create even more complexity, with many "duplicate" JS libs in PHP for Symfony. Mixing UX packages with native JS libs will quickly be an hell.
Good UX in JS is complicated for sure, it's a profession in its own right. Developers should be aware of that and performs their skills in this domain instead of delaying this learning with such a concept as SymfonyUX. I'm sorry but the example of CharJS in this article shoked me, mixing PHP/JS concerns...
But the worst is my experence installing Webpack Encore yesterday, for a testing project. I see Stimulus things popping, controller.js, bootsrap.js,... I was wondering what happened, maybe a was installing the wrong package, but no. Stimulus is now by default installed with Webpack Encore instead of letting us the choice of our frontend conception. I'm not gonna lie, I was a little upset about it.
So I decided to not use Webpack Encore anymore and use native Webpack instead. This will let me the choice of what I want to use.
I feel very sorry because I know it's a lot of work from all of you, but I will definitely not join you in this vision of fronted concerns.
@Jonathan that's fine, you definitely can opt-out of using Stimulus! (by the way, no need to remove Encore, you can simply configure it as you would in any Symfony 5.1 app and remove the stimulus-bridge usage).
However, it's important to note that Stimulus doesn't replace and replicate JS libs in any way. You can view Stimulus controllers (and thus UX packages) as equivalents of the Symfony bundles: they link existing JS packages libraries with Symfony, they do not replace anything.
In any JS framework out there you will find these link libraries: react-chartjs, vue-chartjs, ... If you wish to keep using React/Vue/Angular, that's easy to do: either you can remove Stimulus entirely, or you can use a single Stimulus controller to route a DOM node built by Twig to a React/Vue/... app. It's really up to you.
For instance: https://gist.github.com/tgalopin/f980149f95714293adee05cf11a85202
I would advise you to consider keeping Stimulus in your app though, even if you don't use it and transfer everything to React/Vue/... The main reasoning behind this is that by doing so, you allow vendor libraries to expose their JavaScript in your app. A good example of this is EasyAdmin: by leveraging Symfony UX, EasyAdmin will be able to create reusable components and let you add you own JS in its code very easily. Symfony UX provides a foundation on which things can be built upon, without preventing you to use any other technology on top.
Finally, about mixing PHP with JS: it can be very useful in some cases and very bad in others. I will never promote the hiding of JavaScript for the sake of not learning a new language: Symfony UX does not aim at that. However, in cases like Charts, transmitting data from backend to frontend can be cumbersome or even insecure (and the other way around too). Using a library that does it for you is very useful.
To create a good ecosystem you need to have use cases where having a mix of php and javascript takes a while to integrate.
For example the ux-dropzone package. This seems a lot of code that can be done by using dropzone.js and add the dropzone class to the form. No need to crop on the server.
It's possible with other frameworks to target DOM nodes, using stimulus an Vue together seems overkill to me.
I think it is a good idea but it needs better use cases. I believe someone on the chat during SymfonyWorld online suggested collections. This is a form behaviour a lot of us need to implement to get it working.
In my comment yesterday I mixed the dropzone package with the cropper package. You don't need to crop on the server.
Sorry for my opinion but it looks like politic decision. Seem idea promote js libs by Symfony popularity. There too much js libs/tools and no need create new one just add bridges for existing. I saw it from encore. I think all js way is wrong especially mix php and js like menthoned @Jonathan. When we talk about webpack no need reinventing the wheel. I think current state need tools which can forward env, routes params from php to js. Above example move us to jquery time but why then use webpack and modern concept.
Maybe better to have two ways jquery and modern spa like concepts and UX initiatives. Who want mesh and let use jquery ways who want clean code and separate parts let use spa-like ways.
I see that i can not use current UX but i like Symfony and i want that it used as backend on modern js apps.
Looks very promising !
It has often been a struggle to pass data from the complete chain that we all kinda use :
Controller to > Twig to > HTML data attributes storing a json_encode of some twig variable to > add an entry on Encore webpack.config to > finaly the js endpoint file that, still, need to detect that html element, read the content of the data attributes to be able to use it in some way (ex: draw a chart).
Here it's pretty elegant to have the chart being initialize in PHP, then simply calling render_chart on Twig.
Definitely gonna try that.
Why not for FullCalendar ?
Awesome initiative! thank you
thanks for this!!!! my dream is a super simple package with select2.
I think that Symfony UX is a good initiave to include JavaScript files in a easy way. Everything that makes our development job easier should be always welcome, isn´t it? In addition to UX Dropzone, UX SWUP, etc. it would be nice to have someday a "UX AutocompleteForm" that allows us to build a small search engine based on API Platform. Great job and we will love to see Symfony UX growing in 2021. 👍😊
Great initiative, love it!!
👋 Hi guys, I've just published an article, where I tried to take a look at Symfony UX from a business/product owner perspective. More in the article https://advanced-developer.medium.com/introducing-the-symfony-ux-a3be202bc643
This looks like wrong way of doing things.
Many tried to do similar thing in-before, including Drupal - didn't aged well. Many such cases.
Great thing ,would be a great improvement for the framework