Formularios sin clase de datos
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeEstamos casi en la línea de meta de nuestro viaje con Symfony Forms. Pero antes de terminar, vamos a sumergirnos en algo divertido y práctico a la vez. Si navegas a la página /parts, verás una simple entrada de búsqueda. Es un formulario HTML básico, y eso está muy bien. Pero he aquí una idea: ¿podemos recrear esto utilizando Symfony Forms? ¡Por supuesto!
Crear un formulario sin una entidad
Cuando hablamos de Formularios Symfony, solemos vincularlos a una entidad o a una clase de datos. Sin embargo, esto no es inamovible. Los Formularios Symfony pueden funcionar solos, sin ningún mapeo de objetos entre bastidores. Todos los datos del formulario se almacenan en matrices PHP. Nuestro formulario de búsqueda es un gran ejemplo de esto.
Por supuesto, podríamos crear este formulario directamente en el controlador utilizando el constructor de formularios. Pero para mantener las cosas limpias y ordenadas, vamos a seguir con el tipo de formulario. Además, aprenderemos algunos trucos útiles por el camino.
Dirígete a tu terminal y ejecuta el siguiente comando:
symfony console make:form
Nombra el formulario PartSearchType. Esta vez, cuando te pida una entidad o clase de datos, déjalo en blanco. A continuación, localiza elPartSearchType generado en el directorio src/Form y ábrelo.
Verás un campo marcador de posición llamado field_name:
| // ... lines 1 - 8 | |
| class PartSearchType extends AbstractType | |
| { | |
| public function buildForm(FormBuilderInterface $builder, array $options): void | |
| { | |
| $builder | |
| ->add('field_name') | |
| ; | |
| } | |
| public function configureOptions(OptionsResolver $resolver): void | |
| { | |
| $resolver->setDefaults([ | |
| // Configure your form options here | |
| ]); | |
| } | |
| } |
Cámbialo por query para que coincida con el nombre de la entrada de búsqueda heredada:
| // ... lines 1 - 8 | |
| class PartSearchType extends AbstractType | |
| { | |
| public function buildForm(FormBuilderInterface $builder, array $options): void | |
| { | |
| $builder | |
| ->add('query') | |
| ; | |
| } | |
| // ... lines 17 - 23 | |
| } |
Utilizar el formulario en el controlador
Ahora, dirígete a la acción index() en src/Controller/PartController.php. Al principio, crea un formulario con $this->createForm() pasandoPartSearchType::class y guárdalo en una variable llamada $searchForm. Al renderizar la plantilla de abajo, pásala como parámetro adicional con'searchForm' => $searchForm:
| // ... lines 1 - 4 | |
| use App\Form\PartSearchType; | |
| // ... lines 6 - 11 | |
| final class PartController extends AbstractController | |
| { | |
| // ... line 14 | |
| public function index(StarshipPartRepository $repository, Request $request,): Response | |
| { | |
| $searchForm = $this->createForm(PartSearchType::class); | |
| // ... lines 18 - 21 | |
| return $this->render('part/index.html.twig', [ | |
| // ... line 23 | |
| 'searchForm' => $searchForm, | |
| ]); | |
| } | |
| } |
En templates/part/index.html.twig, renderiza todo el formulario con{{ form(searchForm) }}:
| // ... lines 1 - 4 | |
| {% block body %} | |
| <div class="flex justify-end mt-6 mb-6"> | |
| <div class="relative w-full max-w-md"> | |
| <form method="get" action="{{ path('app_part_index') }}"> | |
| // ... lines 10 - 18 | |
| </form> | |
| {{ form(searchForm) }} | |
| </div> | |
| </div> | |
| // ... lines 24 - 48 | |
| {% endblock %} |
Por ahora, conservemos el original para poder compararlos. Ya lo arreglaremos más adelante.
Después de actualizar tu navegador, verás dos entradas de búsqueda. La nueva tiene una etiqueta, mientras que la antigua no la tiene. Vamos a solucionar esto primero.
Ocultar la etiqueta del campo de formulario
De vuelta en PartSearchType, para el campo query, pasa null para el tipo, y un array para las opciones. Dentro de ella, añade la opción label. Puedes establecerla en cualquier cadena que quieras que sea la etiqueta. O, simplemente, ponle false. Esto indica a Symfony que no muestre la etiqueta:
| // ... lines 1 - 8 | |
| class PartSearchType extends AbstractType | |
| { | |
| public function buildForm(FormBuilderInterface $builder, array $options): void | |
| { | |
| $builder | |
| ->add('query', null, [ | |
| 'label' => false, | |
| ]) | |
| ; | |
| } | |
| // ... lines 19 - 25 | |
| } |
Ya que estamos aquí, pulamos un poco las cosas. Añade la opción attr para los atributos, y dentro de ella, añade placeholder ajustado a Search... para que coincida con el formulario heredado. En la siguiente línea, class. Coge las clases CSS del formulario original y pégalas aquí:
| // ... lines 1 - 8 | |
| class PartSearchType extends AbstractType | |
| { | |
| public function buildForm(FormBuilderInterface $builder, array $options): void | |
| { | |
| $builder | |
| ->add('query', null, [ | |
| 'label' => false, | |
| 'attr' => [ | |
| 'placeholder' => 'Search...', | |
| 'class' => 'w-full p-3 pl-10 border border-gray-300 rounded-lg shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500', | |
| ], | |
| ]) | |
| ; | |
| } | |
| // ... lines 23 - 29 | |
| } |
Vuelve a tu navegador y actualiza la página. Ahora debería ser la viva imagen del campo de búsqueda original, menos el icono de búsqueda, del que nos ocuparemos más adelante.
Si intentas enviar el formulario ahora, verás que utiliza el método POST, que es el comportamiento por defecto. Sin embargo, nuestro formulario de búsqueda utiliza GET, que es más adecuado para una función de búsqueda.
¿Y ahora qué?
A continuación, cambiaremos el método del formulario de POST a GET y aprenderemos a gestionarlo correctamente en el controlador.
2 Comments
I believe setting the label to
falseremoves it completely. Labels associated with form controls are a crucial accessibility requirement, so you should never set the label tofalse. Theplaceholderattribute is very problematic when it comes to accessibility, and is not a replacement for the form control labels.If you definitely need to hide a form control label, please consider using CSS to hide the label properly so that it remains associated with the control, but is not displayed to the user.
Hey @Inan!
Awesome catch and explanation, I didn't know this! Thanks for the details.
--Kevin
"Houston: no signs of life"
Start the conversation!