Problema al mostrar una coleccion no mapeada de un formulario

185 views
Skip to first unread message

David Teruel Jorge

unread,
Apr 14, 2016, 4:29:18 AM4/14/16
to symfony-es
Hola Sf devs ¡

Tengo un formulario basado en una entity y en el formulario tengo un campo no mapeado, que es una ColectionType::class de un DTO. 

Con la accion de Crear del formulario no hay problema y esta solucionado, el problema viene en la accion de Editar y concretamente a la hora de mostrar esa coleccion no mapeada.

Os pongo un poco de codigo para que veais un poco por donde va.

//OrganizationType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder

      ->//OTROS CAMPOS DE LA ENTITY

      ->add('enrolUserToOrg', CollectionType::class, array(
    'label' => false,
    'entry_type' => new EnrolUserToOrgType($this->selectedRoleUser),
    'mapped' => false,
    'allow_add' => true,
    'delete_empty' => true,
    'attr' => array(
        'class' => 'enrolUserOrgWrapper'
    )
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'efor\AppBundle\Entity\Organization',
));
}


//EnrolUserToOrgType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user', EntityType::class, array(
'label' => false,
'class' => 'UsuarioBundle:User',
'empty_value' => 'Selecciona el/los responsable/s',
'query_builder' => function (EntityRepository $er) {
// return $er->findAllUsersExceptSuperUserAndSuperAdmin();
return $er->createQueryBuilder('users');
},
'attr' => array(
'class' => 'col-md-5 select-user'
)
))
->add('role', ChoiceType::class, array(
'label' => false,
'empty_value' => 'Seleccionar un Rol',
'choices' => $this->roleChoices,
'attr' => array(
'class' => 'col-md-5 select-role'
)
))
->add('Quitar', ButtonType::class, array(
'attr' => array(
'class' => 'col-md-2 btn-danger button-remove-enrol'
)
))
;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'efor\AppBundle\Model\EnrolUserToOrg'
));
}

//DTO -> EnrolUserToOrg
<?php
namespace efor\AppBundle\Model;

use efor\AppBundle\Entity\Role;
use efor\UsuarioBundle\Entity\User;

class EnrolUserToOrg
{
/** @var User $user */
private $user;

/** @var Role $role */
private $role;

/**
* @return User
*/
public function getUser()
{
return $this->user;
}

/**
* @param User $user
*/
public function setUser($user)
{
$this->user = $user;
}

/**
* @return Role
*/
public function getRole()
{
return $this->role;
}

/**
* @param Role $role
*/
public function setRole($role)
{
$this->role = $role;
}
}

Hasta aqui en el formulario de crear una nueva organizacion funciona perfecto, y en el Action del controlador recojo ese campo NO mapeado como un array[EnrolUserToOrg] y creo los objetos y relaciones que necesito.

Mi problema viene ahora al editar el formulario, y es que no se de que forma pasarle el array de elementos del tipo EnrolUserToOrg ( que he obtenido previamente, claro) para que lo añada al campo Collection y pueda mostrarlo en la vista. 
Es decir, hidratar ese campo para que en la vista me llegue esa coleccion rellena.

A alguien se le ocurre alguna idea al respecto ?

Gracias y saludos ¡¡





Manuel Aguirre

unread,
Apr 14, 2016, 9:19:32 AM4/14/16
to symfo...@googlegroups.com
Hola David, podrias en un listener de formulario para el evento SUBMIT, agregar la logica de actualización de la coleccion de elementos en la entidad. Algo como:

$builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
    $organization = $event->getData();
$enrolUserToOrgItems = $event->getForm()->get('enrolUserToOrg')->getData();
    // realizas el update en $organization.
});

Saludos!


--
--
Has recibido este mensaje porque estás suscrito al grupo "symfony-es" de Google Groups.
Para publicar en este grupo, envía un email a symfo...@googlegroups.com
Para darte de baja, envía un email a symfony-es+...@googlegroups.com
El resto de opciones puedes encontrarlas en http://groups.google.com/group/symfony-es?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "symfony-es" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a symfony-es+...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.



--

Manuel Aguirre.


manuel_j555 | Desarrollador de Software | Optime Consulting | twitter | github | Sitio web


A menudo unas pocas horas de "Prueba y error" podrán ahorrarte minutos de leer manuales.

David Teruel Jorge

unread,
Apr 15, 2016, 2:40:13 AM4/15/16
to symfony-es
Hola manuel,

El problema que hay es que ese campo no esta mapeado en la entity y por lo tanto no puedo actualizarlo mediante el objeto $organization.

No se de que forma se puede rellenar ese campo antes de mostrar el formulario en el EditAction, ya que al hacer DEBUG antes de mostrar la vista no me aparece, pero al hacer submit, el DEBUG me muestra que hay una coleccion dentro de $form->getChildren()['modelData']. Es decir, al hacer submit si que me coge la coleccion, pero al mostrar la vista de edicion no.

A ver si se te ocurre alguna solucion.

Gracias¡¡

Saludos ¡¡

Hatler

unread,
Apr 15, 2016, 9:14:31 AM4/15/16
to symfony-es
Hola, como dice Manuel Aguirre, puede ser un listener. y usando la opción

entry_options

un ejemplo de como se usa esta opción:

$builder
->add('favorite_cities', CollectionType::class, array( 'entry_type' => ChoiceType::class, 'entry_options' => array( 'choices' => array( 'Nashville' => 'nashville', 'Paris' => 'paris', 'Berlin' => 'berlin', 'London' => 'london', ), ), ));



Creas una Clase:

<?php

namespace AppBundle\Form\EventListener;

use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormConfigBuilder;
use AppBundle\Form\DataTransformer\UeaToClaveTransformer;


class AddEnrolUserToOrgFieldListener implements EventSubscriberInterface
{
private $em; //Entiti manager
private $builder;

public function __construct($em, $builder)
{
$this->em = $em;
$this->builder = $builder;
}

/**
*
* @return array The event names to listen to
*/
public static function getSubscribedEvents()
{
// Tells the dispatcher that you want to listen on the form.pre_set_data
// event and that the preSetData method should be called.
return array(FormEvents::PRE_SET_DATA => 'onPreSetData');
}

public function onPreSetData(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();

// check if the object is "new"
// If you didn't pass any data to the form, the data is "null".
// This should be considered a new object
if (!$data || !$data->getId()) {
// Si se esta creando una nueva entidad no se hace nada
}else{
// Si se va a editar se rellena con la informacion
// se elimina el campo vacio
$form->remove('enrolUserToOrg');
// se agrega el campo con la informacion

$form->add('enrolUserToOrg', CollectionType::class, array(

    'label' => false,
    'entry_type' => new EnrolUserToOrgType($this->selectedRoleUser)
,
// Agregar Los elementos a mostrar usando la opcion
entry_options

                       'mapped' => false,
    'allow_add' => true,
    'delete_empty' => true,
    'attr' => array(
        'class' => 'enrolUserOrgWrapper'
    )
));
        
}
}
}





Luego simplemente agregas el listener a tu formulario:

$builder
    ->addEventSubscriber(new AddUeaFieldListener($em, $builder))

Manuel Aguirre

unread,
Apr 15, 2016, 11:01:20 AM4/15/16
to symfo...@googlegroups.com
Exacto, con un listener para preSetData tal como dice Hatler.

Me enfonque en el traslado de la info del form al modelo, cuando tu duda era como reflejar la data del modelo en el form.

Otra opción interesante aunque más tediosa es implementar un DataMapper para ese formulario con lo que podras pasar la info del modelo al form y del form al modelo de la forma que desees, con el inconveniente de que deberas hacerlo de forma manual para TODOS los campos del formulario.

Saludos!

--
--
Has recibido este mensaje porque estás suscrito al grupo "symfony-es" de Google Groups.
Para publicar en este grupo, envía un email a symfo...@googlegroups.com
Para darte de baja, envía un email a symfony-es+...@googlegroups.com
El resto de opciones puedes encontrarlas en http://groups.google.com/group/symfony-es?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "symfony-es" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a symfony-es+...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

David Teruel Jorge

unread,
Apr 18, 2016, 3:20:16 AM4/18/16
to symfony-es
Hola, y gracias por contestar.

Voy a probar eso que me habeis dicho y os cuento.

Saludos.
...
Reply all
Reply to author
Forward
0 new messages