将链式表单嵌入到另一个表单中

时间:2015-02-19 09:57:14

标签: forms symfony event-listener

在我的应用程序中,我有两个包(UserBundle和LocationBundle),它们之间有一个OneToOne关联。

LocationFormType链接了国家,州,城市字段表单独立工作正常但当我尝试将表单(LocationFormType)嵌入到UserRegistrationForm时,我无法访问国家/地区对象以检索相关的国家/地区。

Error: Call to a member function getCountry() on a non-object

我喜欢在两种模式下使用LocationFormType,嵌入到另一种形式或独立,可以任何正文帮助我修复我的代码

//LocationFormType
class LocationFormType extends AbstractType {
    protected $em;

    function __construct (EntityManager $em)
    {
        $this->em = $em;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('country', 'entity', array(
                'empty_value' => '--Choose--',
                'class' => 'AppLocationBundle:Country',
                'query_builder' => function(EntityRepository $er)
                {
                    return $er->createQueryBuilder('c')
                        ->where('c.enabled = 1');
                },
                'label' => 'form.country',
                'translation_domain' => 'AppLocationBundle'
            ));

        $builder->addEventSubscriber(new LocationChainedFieldSubscriber($this->em));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'App\LocationBundle\Entity\Location'
        ));
    }

    public function getName()
    {
        return 'app_location_form';
    }
}

位置表格事件订阅者

//EventSubscriber
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormInterface;
use Doctrine\ORM\EntityManager;
use App\LocationBundle\Entity\Country;
use Doctrine\ORM\EntityRepository;


class LocationChainedFieldSubscriber implements EventSubscriberInterface {

protected $em;

function __construct (EntityManager $em)
{
    $this->em = $em;
}

public static function getSubscribedEvents()
{
    return array(
        FormEvents::PRE_SET_DATA => 'preSetData',
        FormEvents::PRE_SUBMIT => 'preSubmit',
    );
}

public function preSetData(FormEvent $event)
{
    $form = $event->getForm();
    $location = $event->getData();

    // Problem occurs here when try to get data, the event data are null
    //How to handle data passed from parent form to child form 

    //Might have an empty account(when we insert a new country)
    $country = $location->getCountry() ? $location->getCountry() : null;
    $this->addElement($form, $country);
}

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

    //The data is not yet hydrated into the entity.
    $country = $this->em->getRepository('AppLocationBundle:Country')->find($data->getCountry());
    $this->addElement($form, $country);
}

protected function addElement(FormInterface $form, Country $country = null)
{

    $states = array();
    if($country)
    {
        //fetch the states form specific a country
        $repo = $this->em->getRepository('AppLocationBundle:State');
        $states = $repo->findByCountry($country, array('name' => 'asc'));
    }

    //Add the state element
    $form->add('state', 'entity', array(
        'choices' => $states,
        'empty_value' => '--Choose--',
        'class' => 'AppLocationBundle:State',
        'mapped' => false
    ));
}

}

将表单位置用作服务

services:
    app_location.form:
    class: App\LocationBundle\Form\Type\LocationFormType
    arguments: ['@doctrine.orm.entity_manager']
    tags:
        - { name: form.type, alias: app_location_form }

嵌入用户注册表单

//UserRegistrationForm
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
       //other fields here
        ->add('name', 'text')
        ->add('location', 'app_location_form', array(
            'data_class' => 'App\LocationBundle\Entity\Location',
            'label' => 'form.location',
            'translation_domain' => 'AppUserBundle'
        ));

    public function getName()
    {
        return 'app_user_profile';
    }
}

1 个答案:

答案 0 :(得分:0)

// UserRegistrationForm

$builder->add('location', 'collection', array('location' => new LocationFormType ()));