Cómo utilizar el cuadro de selección relacionados en otro cuadro de selección?

Cómo usar relacionados con los cuadros de selección en Symfony ?

Digamos, tengo una lista de selección contiene compagnies y otro que contenga los empleados de la empresa seleccionada. ¿Cómo puedo definir aquellos en Symfony?
Ya he creado todos los Javascript de código relacionado, pero cuando la presentación de mi forma y tener errores en algunos campos, el de todos los «sub» seleccionar campos se restablecen a null.

Alguna idea?

Gracias,

EDIT : Como la pregunta parece ser malinterpretado, voy a añadir algunas precisiones :

Descripción :

  1. Que tiene una entidad de la Compañía contiene una lista de los Empleados que utilicen un @OneToMany relación.
  2. Al seleccionar una empresa de seleccionar de la lista desplegable, la segunda lista desplegable que contiene los empleados se actualiza a través de jQuery. Que parte se hace, funciona a la perfección
  3. Cuando se envía el formulario sin errores, el formulario de entidad solución funciona bien.
  4. Cuando se envía el formulario contiene errores, la segunda lista desplegable que contiene todos valores posibles. No son filtrados en la empresa seleccionada.

Trató de soluciones :

  • Mi primera idea fue utilizar el entidad en forma tipo, pensando que el componente podría ser encuadernada de alguna manera en otro campo. es decir. actualización de la lista de los empleados basado en el valor de la empresa seleccionada.

No funciona, no hay manera de salir de la caja para hacer esto. Incluso los que no son de la caja soluciones…

  • Entonces pensé que manualmente pasando la empresa seleccionada como parámetro para el generador de consultas de la segunda lista desplegable.

Pero cuando se crea el formulario, los valores están vacías. Los valores sólo se establecen en bindRequest.

  • Pensamiento sobre el uso de la opción tipo. Delegar todas filtro functionnality a la interfaz de usuario a través de Javascript. Es decir, cuando la carga de la página, una lista vacía aparece y está poblada por Javascript basado en la empresa seleccionada.

Esto realmente funciona, pero creo que no hay otra palabra que realmente realmente feo programación aquí.

PS :

Pregunta se ha hecho aquí, en el Symfony2 lista de correo, en Twitter y el oficial de Symfony 2 foro. Me han buscado en cada una de esas varias veces antes de publicar mis preguntas.

  • Puedes compartir el código por favor?
  • No mucho código para compartir en el hecho. Pero lo que puedo.
  • En un principio se eligió a los empleados de cierta empresa a través de jQuery? Así que, después de enviar el formulario con los errores de este código jquery no es un trabajo y ver a todos los empleados. Compruebe la consola de firebug o chrome deleveloper herramientas de la consola para los errores de js.
InformationsquelleAutor i.am.michiel | 2012-01-29

3 Kommentare

  1. 13

    Con respecto a lo que ya ha probado, creo que se debe reintentar la primera/segunda ideas:

    Mi primera idea fue utilizar el formulario tipo de entidad, el pensamiento de la componente
    podría ser encuadernada de alguna manera en otro campo. es decir. actualización de la lista de empleados
    basado en el valor de la empresa seleccionada.

    Puede rellenar los empleados de la caja de selección utilizando el entity tipo.
    Todo lo que tienes que hacer es definir las buenas opciones:

    class FooType extends AbstractType
    {
        public function buildForm(FormBuilder $builder, array $options)
        {
            $builder
                ->add('employee', 'entity', array(
                    'class' => 'Entity\Employee',
                    'query_builder' => function ($repository) use($options) {
                        return $repository
                            ->createQueryBuilder('e')
                            ->where('e.company = :company')
                            ->setParameter('company', $options['companyId'])
                        ;
                    },
                ))
            ;
        }
    
        public function getDefaultOptions(array $options)
        {
            return array('data_class' => 'Entity\Foo', 'companyId' => null);
        }
    }

    Entonces pensé manualmente pasando la empresa seleccionada como
    parámetro para el generador de consultas de la segunda lista desplegable.

    El ejemplo aquí filtros de la lista de los empleados basado en la companyId del formulario de opción.
    Usted puede modificar este comportamiento mediante el filtrado directamente en la empresa presente en los datos del formulario.

    public function buildForm(FormBuilder $builder, array $options)
    {
        $companyId = $builder->getData()->getCompanyId();
        $builder
            ->add('employee', 'entity', array(
                'class' => 'Entity\Employee',
                'query_builder' => function ($repository) use ($companyId) {
                    return $repository
                        ->createQueryBuilder('e')
                        ->where('e.company = :company')
                        ->setParameter('company', $companyId)
                    ;
                },
            ))
        ;
    }

    Usted todavía tiene que implementar la getEmployee() y setEmployee() métodos en su Entity\Foo clase.

    Pero cuando se crea el formulario, los valores están vacías. Los valores sólo se establecen en
    bindRequest.

    No. Los valores se definen al crear un formulario utilizando el formulario de fábrica (tercer argumento),
    O cuando usted llame a $form->setData($foo);. Los datos se modifican cuando bind de las nuevas aportaciones a la forma.

    Podría haber un problema con este enfoque: es posible que el id de empleado vinculado a la forma no está disponible en el formulario de la lista de opciones, porque ha cambiado la empresa (y por lo tanto los empleados).

    • Muchas gracias Florian 🙂 Que me ayudaron a salir ni siquiera se puede creer cómo !!!
  2. 6

    Yo tenía el mismo problema. Debe utilizar el formulario de eventos. Mi ejemplo de código con el país, la región, la ciudad de las relaciones.

    namespace Orfos\UserBundle\Form\Type;
    
    ///import form events namespace
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Symfony\Component\Form\FormEvents;
    use Symfony\Component\Form\Event\DataEvent;
    
    class RegistrationFormType extends BaseType
    {
    
        private $request;
    
        public function __construct($class, $request, $doctrine)
        {
            parent::__construct($class);
            $this->request = $request;
            $this->doctrine = $doctrine;
        }
    
        public function buildForm(FormBuilder $builder, array $options)
        {
            parent::buildForm($builder, $options);
            //other fields
    
            $locale = $this->request->getLocale();
    
            $builder->add('country', 'entity', array(
                'class' => 'Orfos\CoreBundle\Entity\Country',
                'property' => $locale . 'name',
                'label' => 'register.country.label',
                'query_builder' => function(EntityRepository $er) {
                    return $er->createQueryBuilder('c')
                                    ->select('c', 't')
                                    ->join('c.translations', 't');
                },
            ));
    
            $factory = $builder->getFormFactory();
            $refreshRegion = function ($form, $country) use ($factory, $locale) {
                        $form->add($factory->createNamed('entity', 'region', null, array(
                                    'class' => 'Orfos\CoreBundle\Entity\Region',
                                    'property' => $locale . 'name',
                                    'label' => 'register.region.label',
                                    'query_builder' => function (EntityRepository $repository) use ($country) {
                                        $qb = $repository->createQueryBuilder('region')
                                                ->select('region', 'translation')
                                                ->innerJoin('region.country', 'country')
                                                ->join('region.translations', 'translation');
    
                                        if ($country instanceof Country) {
                                            $qb = $qb->where('region.country = :country')
                                                    ->setParameter('country', $country);
                                        } elseif (is_numeric($country)) {
                                            $qb = $qb->where('country.id = :country_id')
                                                    ->setParameter('country_id', $country);
                                        } else {
                                            $qb = $qb->where('country.id = 1');
                                        }
    
                                        return $qb;
                                    }
                                )));
                    };
            $factory = $builder->getFormFactory();
            $refreshCity = function($form, $region) use ($factory, $locale) {
                        $form->add($factory->createNamed('entity', 'city', null, array(
                                    'class' => 'Orfos\CoreBundle\Entity\City',
                                    'property' => $locale . 'name',
                                    'label' => 'register.city.label',
                                    'query_builder' => function (EntityRepository $repository) use ($region) {
                                        $qb = $repository->createQueryBuilder('city')
                                                ->select('city', 'translation')
                                                ->innerJoin('city.region', 'region')
                                                ->innerJoin('city.translations', 'translation');
    
                                        if ($region instanceof Region) {
                                            $qb = $qb->where('city.region = :region')
                                                    ->setParameter('region', $region);
                                        } elseif (is_numeric($region)) {
                                            $qb = $qb->where('region.id = :region_id')
                                                    ->setParameter('region_id', $region);
                                        } else {
                                            $qb = $qb->where('region.id = 1');
                                        }
    
                                        return $qb;
                                    }
                                )));
                    };
    
            $builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) use ($refreshRegion, $refreshCity) {
                        $form = $event->getForm();
                        $data = $event->getData();
    
                        if ($data == null){
                            $refreshRegion($form, null);
                            $refreshCity($form, null);
                        }
    
                        if ($data instanceof Country) {
                            $refreshRegion($form, $data->getCountry()->getRegions());
                            $refreshCity($form, $data->getRegion()->getCities());
                        }
                    });
    
            $builder->addEventListener(FormEvents::PRE_BIND, function (DataEvent $event) use ($refreshRegion, $refreshCity) {
                        $form = $event->getForm();
                        $data = $event->getData();
    
                        if (array_key_exists('country', $data)) {
                            $refreshRegion($form, $data['country']);
                        }
                        if (array_key_exists('region', $data)) {
                            $refreshCity($form, $data['region']);
                        }                    
                    });
        }
    
    }
    • Gracias por tu solución, podría crear a partir de su idea de un tipo genérico para crear encadenado listas desplegables.
    • Hola Pivasyk. Su entrada en este post es muy interesante. Gracias por eso. Podría usted por favor decirme si el país, la región y la ciudad se establecen en una entidad o son 3 diferentes entidades vinculadas?
    • hm… no entiendo tu pregunta… Es de 3 diferentes entidades con relación de uno a muchos, el 4 de entidad usuario vinculado a la ciudad, la región y el país
  3. 0

    Puede crear la acción, que será devolver json array con los empleados de la empresa.
    Cuando la lista de empresas cambiado usted debe solicitar esta acción por ajax y seleccione crear lista de los empleados.

    Formulario de acción de controlador:

    /**
     * @Route("/job", name="_demo_job")
     * @Template()
     */
    public function jobAction()
    {
        $form = $this->createForm(new JobType());
    
        $request = $this->getRequest();
        if ($request->getMethod() == 'POST') {
            $form->bindRequest($request);
            $data = $form->getData();
            //some operations with form data
        }
    
        return array(
            'form' => $form->createView(),
        );
    }

    Conroller, que devuelven a los empleados de la compañía en json:

    /**
     * Finds all employees by company
     *
     * @Route("/{id}/show", name="employees_by_category")
     */
    public function listByCompanyAction($id)
    {
        $request = $this->getRequest();
    
        if ($request->isXmlHttpRequest() && $request->getMethod() == 'POST') {
            $em = $this->getDoctrine()->getEntityManager();
    
            $company = $em->getRepository('AcmeDemoBundle:Company')->find($id);
    
            //create array for json response
            $empoloyees = array();
            foreach ($company->getEmployees() as $employee) {
                $empoloyees[] = array($employee->getId(), $employee->getName());
            }
    
            $response = new Response(json_encode($empoloyees));
            $response->headers->set('Content-Type', 'application/json');
    
            return $response;
        }
        return new Response();
    }

    Plantilla de formulario:

    <script type="text/javascript">
        $(document).ready(function() {
            $('#form_company').change(function() {
                var companyId = $(this).val();
                $.post('{{ route }}/' + companyId + '/show', function(data) {
                    //last selected employee
                    var selectedVal = $('option:selected', '#form_employee').attr('value');
    
                    $('#form_employee option').remove();
                    for (i in data) {
                        //create option with employee
                        var option = $('<option></option>').
                            attr('value', data[i][0]).
                            text(data[i][1]);
                        //set selected employee
                        if (data[i][0] == selectedVal) {
                            option.attr('selected', 'selected');
                        }
                        //append to employee to employees select
                        $('#form_employee').append(option);
                    }
                }, 'json');
            })
    
            //request employees by company
            $('#form_company').change();
        })
    
    </script>
    <form action="{{ path('_demo_job') }}" method="post" {{ form_enctype(form) }}>
        {{ form_widget(form) }}
    
        <input type="submit" />
    </form>

    Para más detalles ejemplo, usted debe describir el problema en detalle.

    • Gracias por la respuesta y el esfuerzo, pero como te habrás dado cuenta, en mis preguntas me indicó claramente todos los jQuery json parte ya está implementado.
    • En mi selecciona variante no se restablecen. Usted debe compartir su js y forma el generador de la acción que yo trate de encontrar el problema.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea