Buy Access to Course
08.

Paquetes Symfony UX

|

Share this awesome video!

|

Keep on Learning!

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Visita https://ux.symfony.com. Este es el sitio de la Iniciativa Symfony UX: un grupo de paquetes PHP y JavaScript que nos proporcionan controladores Stimulus gratuitos. Hay un controlador Stimulus que puede renderizar chart.js, otro que puede añadir un recortador de imágenes, etc.

Hoy vamos a centrarnos en conseguir un controlador Stimulus gratuito que nos proporcione un elegante elemento autocompletar select. Puedes buscar, seleccionar... es todo muy bonito.

En nuestro sitio, dirígete a la sección de viajes y pulsa editar. El formulario tiene un desplegable de planetas, que está bien... ¡pero quiero darle más asombroso!

Instalar UX Autocompletar

Vamos a instalar este paquete. La librería UX Autocompletar es una mezcla de PHP con un controlador Stimulus en su interior. Copia la línea composer require y pégala:

composer require symfony/ux-autocomplete

Cuando termine... Ejecuta:

git status

Oooh: la receta modificó dos cosas interesantes: controllers.json y importmap.phpSabemos que todo lo que haya en el directorio assets/controllers/ estará disponible como controlador Stimulus. Además, todo lo que esté en controllers.jsontambién se registrará como controlador Stimulus:

{
"controllers": {
"@symfony/ux-autocomplete": {
"autocomplete": {
"enabled": true,
"fetch": "eager",
"autoimport": {
"tom-select/dist/css/tom-select.default.css": true,
"tom-select/dist/css/tom-select.bootstrap5.css": false
}
}
}
},
"entrypoints": []
}

Es una forma de que los paquetes PHP de terceros añadan más controladores. La receta ha añadido esta entrada, lo que básicamente significa que cogerá algo de código del paquete que acabamos de instalar y lo registrará como controlador Stimulus.

El caso es que ahora tenemos un tercer controlador Stimulus en nuestra aplicación El otro cambio que hizo la receta está en importmap.php: añadió una nueva entrada para tom-select:

34 lines | importmap.php
// ... lines 1 - 15
return [
// ... lines 17 - 29
'tom-select' => [
'version' => '2.3.1',
],
];

tom-select es un paquete JavaScript... y en realidad es lo que hace el trabajo pesado para la funcionalidad de autocompletar. Este controlador de Stimulus es sólo una pequeña envoltura alrededor de tom-select. Y así, como ese controlador necesita tom-select, ¡se añadió!

UX "autoimportar" CSS

Pero cuando actualizamos la página, nos encontramos con un error encantador. Dice

No se ha podido encontrar el autoimport tom-select.default.css en importmap.php. Prueba a ejecutar importmap:require y luego esa ruta.

Vuelve a mirar en controllers.json. A veces, estos controladores tienen una sección extra llamada autoimport:

16 lines | assets/controllers.json
{
"controllers": {
"@symfony/ux-autocomplete": {
"autocomplete": {
// ... lines 5 - 6
"autoimport": {
"tom-select/dist/css/tom-select.default.css": true,
"tom-select/dist/css/tom-select.bootstrap5.css": false
}
}
}
},
// ... line 14
}

La idea es que un controlador Stimulus puede tener un archivo CSS que lo acompañe. Esta sección te permite activar o desactivar esos archivos CSS. Por ejemplo, con tom-select, hay un archivo CSS por defecto. O si utilizas Bootstrap, puedes utilizar el archivo CSS de Bootstrap 5. Podríamos poner esto en false y esto en true.

Una diferencia entre utilizar módulos JavaScript en un navegador frente a Node y Webpack es la cantidad de paquete que obtienes. Con Node, cuando escribes npm add tom-select, se descarga todo el paquete: los archivos JavaScript, los archivos CSS y todo lo demás. Pero con AssetMapper y el entorno del navegador en general, cuando importmap:require tom-select, descargas un único archivo: sólo el archivo JavaScript. Los archivos CSS no están ahí.

Sin embargo, con importmap:require, podemos, por supuesto, coger un paquete con su nombre, así:

php bin/console importmap:require tom-select

Genial. Pero también podemos importar una ruta de archivo específica dentro de ese paquete. Y, como AssetMapper admite archivos CSS, esa ruta puede ser a un archivo CSS.

En otras palabras, si necesitamos este archivo CSS del proveedor, podemos obtenerlo con:

php bin/console importmap:require tom-select/dist/css/tom-select.default.css

¡Lo tengo! En el directorio assets/vendor/... ¡ahí está! Y enimportmap.php, también está ahí. Esto significa que está disponible para que lo importe nuestro controlador Stimulus.

¿El resultado final? ¡El error ha desaparecido! Y en el código fuente de la página, está el archivo CSS.

Aplicar la función Autocompletar a un campo

Vale, después de una llamada a composer require, una llamada a importmap:require y un montón de parloteos míos, tenemos un nuevo controlador Stimulus de autocompletar listo para funcionar.

Podríamos añadir un data-controller al elemento select. Pero recuerda: Los paquetes UX suelen ser una mezcla de controladores Stimulus y código PHP. En este caso, el código PHP nos permite activar el controlador directamente en nuestro formulario. Abresrc/Form/VoyageType.php. El campo planet es un EntityType:

34 lines | src/Form/VoyageType.php
// ... lines 1 - 10
class VoyageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
// ... lines 16 - 19
->add('planet', null, [
'choice_label' => 'name',
'placeholder' => 'Choose a planet',
])
;
}
// ... lines 26 - 32
}

Y, gracias al nuevo paquete, cualquier EntityType o ChoiceType tiene ahora una opciónautocomplete. Ponlo en true:

35 lines | src/Form/VoyageType.php
// ... lines 1 - 10
class VoyageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
// ... lines 16 - 19
->add('planet', null, [
// ... lines 21 - 22
'autocomplete' => true,
])
;
}
// ... lines 27 - 33
}

Y ahora... ¡Tachán! Puede que a la policía de la moda no le encante esto, ¡pero funciona! Esa opción activó el controlador Stimulus: incluso puedes verlo en la página. Aquí está el select ahora con un data-controller seguido del nombre largo de ese controlador.

Personalizar el CSS

¿Cómo podemos mejorar este aspecto? Gracias al autoimport, eltom-select.default.css al menos hace que se vea bien. Si estuviéramos usando Bootstrap, cambiaría esto por true, esto por false, importmap:require el archivo Bootstrap y estaríamos bien.

Ahora mismo, no hay soporte oficial para Tailwind, así que le daremos estilo manualmente. En assets/styles/app.css, quitaré body. Además de las cosas de Tailwind, puedes pegar cualquier estilo personalizado que necesites. Estos anulan algunos de los estilos predeterminados para que se vean bien en nuestro modo oscuro con temática espacial:

@tailwind base;
@tailwind components;
@tailwind utilities;
body {
background-color: skyblue;
}
/* tom-select custom styling */
/* Base Styles for Dark Mode */
.ts-wrapper {
@apply border-gray-600;
}
.ts-wrapper .ts-control,
.ts-wrapper.single .ts-control,
.ts-wrapper.single.input-active .ts-control,
.full .ts-control,
.ts-dropdown {
@apply bg-gray-800 text-white !important;
box-shadow: none !important;
background-image: none !important;
border: none !important;
}
/* Specific Style for the Input Field */
.ts-wrapper .ts-control > input,
.ts-wrapper.single .ts-control > input {
@apply bg-transparent text-white;
}
.ts-wrapper .ts-dropdown .option {
@apply bg-gray-800 text-white;
}
/* Active and Hover States for Dropdown Items */
.ts-wrapper .ts-dropdown .active,
.ts-wrapper .ts-dropdown [data-selectable]:hover {
@apply bg-gray-700 text-white;
}
/* Disabled and Focus States */
.ts-wrapper.disabled .ts-control,
.ts-wrapper.focus .ts-control {
@apply bg-gray-700 text-gray-400 border-gray-500;
}
/* Multi-select Tags Style */
.ts-wrapper.multi .ts-control > div {
@apply bg-gray-600 text-white;
}
/* Border Radius Adjustments */
.ts-wrapper .ts-control,
.ts-wrapper .ts-dropdown,
.ts-wrapper .ts-control > div {
@apply rounded-md;
}
/* Dropdown Box Shadow */
.ts-wrapper .ts-dropdown {
@apply shadow-md;
}

Y ahora... ¡me encanta!

Hacer perezosos los controladores UX

Ah, y ¿recuerdas que podemos hacer que nuestros controladores sean perezosos añadiendo un comentario especial? Podemos hacer lo mismo con los controladores cargados en controllers.json estableciendo fetch en lazy:

16 lines | assets/controllers.json
{
"controllers": {
"@symfony/ux-autocomplete": {
"autocomplete": {
// ... line 5
"fetch": "lazy",
// ... lines 7 - 10
}
}
},
// ... line 14
}

Compruébalo. Ve a la página de viajes. Voy a mis herramientas de red, actualizo y busco "autocompletar"... y "TomSelect". Nada Pero en cuanto vayamos a la página de edición donde se está utilizando: busca "autocompletar". ¡Ahí lo tienes! "TomSelect" y el archivo CSS también se cargaron perezosamente, sólo cuando los necesitábamos.

¡Ya hemos terminado con el día 8! ¡Una semana y un día completos en la ÚLTIMA pila! Mañana, ¡vamos a darle caña y a transformar nuestra aplicación en una maravilla elegante de una sola página con Turbo! En los próximos 7 días... las cosas empezarán a volverse locas.