Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Crear un campo de formulario personalizado de tipo "entity"

20 de febrero de 2015

Hola,

Me he dado cuenta de que utilizo en bastantes formularios un campo de tipo entity para seleccionar tamaños de una imagen.

/**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('nombre')
            ->add('descripcion')
            ->add('tamanyoImagen', 'entity', array(
                    'class' => 'RM\PlantillaBundle\Entity\TamanyoImagen',
                    'em' => $options['em'],
                    'query_builder' => function(EntityRepository $er){
                        return $er->createQueryBuilder('t')
                            ->where('t.tipo = :tipo')
                            ->andWhere('t.estado > -1')
                            ->setParameter('tipo', TamanyoImagen::PRODUCTO);
                    },
                    'property' => 'codigo',
                    'empty_value' => 'Tamaño de Imagen',
                    'empty_data' => null,
                    'required' => false
                ) )
            ->add('estado', 'hidden', array(
                    'data' => 1
                ))
        ;
    }

Como lo utilizo en bastantes sitios, me gustaría crear un nuevo tipo para poder reutilizar el código. Pero estoy teniendo bastantes problemas incluso después de haber leído la documentación de Symfony.

¿Podríais indicarme los pasos a seguir para crearlo?

Muchas gracias de antemano y un saludo.


Respuestas

#1

Buen día, para crearlo deberás crear tu clase Type de la siguiente manera:

// src/AppBundle/Form/Type/TamanyoImagenType.php
namespace AppBundle\Form\Type;
 
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
 
class TamanyoImagenType extends AbstractType
{
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'class' => 'RM\PlantillaBundle\Entity\TamanyoImagen',
            'query_builder' => function(EntityRepository $er){
                return $er->createQueryBuilder('t')
                    ->where('t.tipo = :tipo')
                    ->andWhere('t.estado > -1')
                    ->setParameter('tipo', TamanyoImagen::PRODUCTO);
             },
             'property' => 'codigo',
             'empty_value' => 'Tamaño de Imagen',
             'empty_data' => null,
             'required' => false
        ));
    }
 
    public function getParent()
    {
        return 'entity';
    }
 
    public function getName()
    {
        return 'tamanyo_imagen';
    }
}

Luego para usarlo es:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('nombre')
        ->add('descripcion')
        ->add('tamanyoImagen', new TamanyoImagenType())
        ->add('estado', 'hidden', array('data' => 1));
    }

Más info Acá, Saludos!

@manuel_j555

20 febrero 2015, 14:51
#2

Actualización: escribí mi comentario sin ver el que estaba escribiendo @manuel_j555. Su respuesta es la mejor si quieres seguir utilizando un campo de tipo entity. La solución que te indicaba a continuación quizás es más adecuada para otros ejemplos más sencillos.


Tienes razón en que la documentación de Symfony sobre crear tipos de formulario propios es demasiado avanzada para casos sencillos como este. Te recomiendo en su lugar este artículo que aunque es muy viejo, explica bien el proceso:

  1. Creas un campo que extienda de AbstractType pero cuyo padre sea el tipo Choice.
  2. Creas una clase que implemente ChoiceListInterface y que devuelva la lista de opciones que se mostrarán al usuario.
  3. La clave está en definir un servicio para esa clase que implementa ChoiceListInterface, de manera que puedas inyectarle el entity manager de Doctrine o el repositorio concreto sobre el que vas a hacer las búsquedas.
  4. Registras el campo creando un servicio etiquetado con form.type y ya puedes usarlo en tus formularios.

@javiereguiluz

20 febrero 2015, 14:57
#3

Hola @manuel_j555, lo primero muchísimas gracias por responder tan rápido.

Lo tenia hecho tal y como me has dicho, pero me daba una Excepcion diciendo que faltaba la opción data. Creo que estaba confundiendo la opción class y data_class.

A parte del código que has puesto, he creado un servicio para poder utilizarlo en cualquier parte:

rm_plantilla.form.tamanyoimagen:
      class: RM\PlantillaBundle\Form\TamanyoImagen\TamanyoImagenType
      tags:
        - { name: form.type, alias: tamanyoImagen }

De esta forma puedes utilizarlo de la siguiente manera:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('nombre')
        ->add('descripcion')
        ->add('tamanyoImagen', 'tamanyoImagen')
        ->add('estado', 'hidden', array('data' => 1));
 }

@javiermadueno

20 febrero 2015, 15:01
#4

@javiereguiluz gracias a ti también por la respuesta. También le había echado un vistazo al artículo que has enlazado. El caso es que lo estaba haciendo bien, tal y como ha explicado @manuel_j555, pero no estaba indicando la opción class sino data_class y ahí estaba el problema.

Por cierto, me gustaría profundizar algo más en el uso de los formularios de Symfony, ¿Conoces algún recurso que pueda utilizar? (A parte de la documentación oficial de Symfony) Creo que se le pueden sacar mucho partido si se saben utilizar de manera correcta.

Muchas gracias y un saludo.

@javiermadueno

20 febrero 2015, 16:58