Symfony UX: La nueva iniciativa para el ecosistema JavaScript

symfony-ux.png
Solucionex
07
Dic 20

Durante las últimas semanas el blog oficial de Symfony ha estado muy activo: PHP 8 para Symfony Cloud y la nueva versión 5.2 han sido (entre otras) algunas de ellas. Hace solo unos días han presentado Symfony UX, la nueva iniciativa para el ecosistema JavaScript relacionado con Symfony.

El proyecto se centra ser la equivalencia del ya conocido Symfony Flex para el entorno del frontend, integrando estos componentes con su parte en el backend, para de este modo agilizar al máximo la creación de nuevas funcionalidades de cara al usuario final.

 

¿En qué consiste?

Symfony UX nos provee una serie de herramientas que hacen de puente entre Symfony y nuestro ecosistema frontend/JavaScript. Sigue los estándares sugeridos por los gigantes como npm, Webpack Encore y Stimulus.

No está vinculado a ningún framework. Puedes utilizar React, Vue, Angular, se basa en el estándar HTML y puede ser adoptado progresivamente en aplicaciones existentes.

Se componete de 3 componentes principales:

  • Una integración entre Symfony y Stimulus que provee una nueva orgnización para el código JS.
  • Actualiza automáticamente nuestras dependencias de Symfony Flex y Webpack. De este modo tenemos configuradas de forma automática nuestras dependencias necesarias en ámbos contextos.
  • Una serie de paquetes en el core del UX que nos permitirán desarrollar ágilmente nuestras interfaces.

 

Ejemplo de uso: Symfony UX Dropzone

Instalación

La mejor manera de ver en que consiste todo esto es con un ejemplo. A modo de ilustración mostraré el uso de Symfony UX Dropzone. Este componente nos crea todas las dependencias y configuración para crear la típica zona de “arrastra aquí tus archivos” de un formulario, con todas las dependencias JS y CSS internas así como su integración con el componente Form de modo automático.

Lo primero que debemos es actualizar las dependencias de Symfony Flex y Webpack Encore.

composer update symfony/flex
yarn upgrade "@symfony/webpack-encore@^0.32.0"

Y actualizamos todas nuestras recetas a la última versión (ojo, esto puede sobreescribirnos código, revisar manualmente):

composer recipes:install symfony/webpack-encore-bundle --force -v

De ahora en adelante, Symfony Flex reaccionará a cualquier paquete PHP que instales y contenga código JS. Como hemos comentado, vamos a ver el ejemplo de Symfony UX Dropzone, primero lo añadimos:

composer require symfony/ux-dropzone

Esto nos genera las configuraciones necesarias en el ficheros package.json y assets/controllers.json, este último seguramente menos conocido:

{
    "controllers": {
        "@symfony/ux-dropzone": {
            "dropzone": {
                "enabled": true,
                "webpackMode": "eager",
                "autoimport": {
                    "@symfony/ux-dropzone/src/style.css": true
                }
            }
        }
    },
    "entrypoints": []
}

a continuación:

# Instalamos las dependencias JS y compilamos
yarn install --force
yarn encore dev

...y voila! Tendríamos todo configurado y listo para usar el componente Dropzone en nuestros formularios para carga de ficheros.

Uso

Su uso muy sencillo, básicamente debido a que en la parte Symfony se utiliza como un sustituto de la clase nativa FileType:

// ...
use Symfony\UX\Dropzone\Form\DropzoneType;

class CommentFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // ...
            ->add('photo', DropzoneType::class)
            // ...
        ;
    }

    // ...
}
Personalización

En el caso que estamos viendo, Dropzone provee una serie de estilos CSS por defecto, si deseamos personalizarlo, podemos indicar que no importe estos estilos por defecto del siguiente modo en el fichero controllers.json:

"autoimport": { "@symfony/ux-dropzone/src/style.css": true }

Extender el comportamiento por defecto

Symfony UX Dropzone nos permite extender el comportamiento por defecto del controlador Stimulus:

// mydropzone_controller.js

import { Controller } from 'stimulus';

export default class extends Controller {
    connect() {
        this.element.addEventListener('dropzone:connect', this._onConnect);
        this.element.addEventListener('dropzone:change', this._onChange);
        this.element.addEventListener('dropzone:clear', this._onClear);
    }

    disconnect() {
        // You should always remove listeners when the controller is disconnected to avoid side-effects
        this.element.removeEventListener('dropzone:connect', this._onConnect);
        this.element.removeEventListener('dropzone:change', this._onChange);
        this.element.removeEventListener('dropzone:clear', this._onClear);
    }

    _onConnect(event) {
        // The dropzone was just created
    }

    _onChange(event) {
        // The dropzone just changed
    }

    _onClear(event) {
        // The dropzone has just been cleared
    }
}

En el formulario simplemente añadimos el nombre del controlador como un atributo data:

// ...
use Symfony\UX\Dropzone\Form\DropzoneType;

class CommentFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // ...
            ->add('photo', DropzoneType::class, [
                'attr' => ['data-controller' => 'mydropzone'],
            ])
            // ...
        ;
    }

    // ...
}

Symfony UX se presenta como una buena herramienta para agilizar todas estas pequeñas integraciones que se repiten en multitud de proyectos y comparten una base en común. Personalmente me parece una buena iniciativa que ayudará mucho a un desarrollo mucho más ágil de las partes "clásicas" que comparten muchas aplicaciones en sus frontends. 

Desde el proyecto apuntan a que todo esto es algo experimental, animan a contribuir y reportar cualquier bug en sus respectivos repos de GitHub.