Symfony 2 - 如何使用Ajax填充实体字段类型?

时间:2013-01-22 14:11:37

标签: forms symfony doctrine-orm validation

我遇到的问题让我疯狂超过3天,我找不到任何解决方案。尽管如此,我发现stackoverflow上的一篇文章确实是我面临的问题。不幸的是,这个人确实找到了解决方案,但是他或她没有完全分享它。正如他完全解释的那样,只需将其复制粘贴在下面:
顺便说一下,创建该帖子的人似乎只为这个问题创建了自己的帐户,而且从来没有回来过其他事情。这就是为什么我允许自己再次问这里......

  

我有两个实体(A和B)之间有多对一关系   它们。

     

我使用A实体创建表单,并使用实体字段(下拉列表   列表)显示B实体中的行。我使用查询构建器   过滤它们。如果不更改列表中的值(即使用ajax),   一切都很好。

     

但是,如果我动态改变下拉列表中的值,那么当我提交时   表格我有这个错误“这个值无效”

     

这是因为提交的值不包含在“数组”中   由查询构建器返回。

     

似乎这个验证在实体字段的symfony中是自动的   (我在这个领域不使用任何断言)。我想摆脱这个。   但是如何?

似乎我需要实现表单事件。不幸的是,我没有得到它。我阅读了关于该主题非常差的文档,阅读了很多帖子,在互联网上搜索但没有找到任何内容。

以下是我的个人表格类型。我所做的是以下内容。我创建了第一个实体字段类型,其映射属性设置为false,并过滤实体只是为了获取部分。然后我创建另一个称为本地化的实体类型默认情况下,我过滤实体以获取任何内容('')。然后我要填充它是使用Jquery。但不幸的是,我遇到了与其他伙伴相同的问题(见上文)。     

use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use Doctrine\ORM\EntityRepository;
use Auth\GeoBundle\Form\LocalisationType;


class RegistrationFormType extends BaseType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $builder->add('departement', 'entity', array(
            'mapped' => false,
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'departement',
            'query_builder' => function ($repository) {
                return $repository
                    ->createQueryBuilder('e')
                    ->add('groupBy', 'e.departement')
                ;
            },
        ));


        $builder->add('localisation', 'entity', array(
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'formLabel',
            'query_builder' => function ($repository) use ($dpt) {
                return $repository
                    ->createQueryBuilder('e')
                    ->where('e.departement = :dpt')
                    ->setParameter('dpt', '')
                    ->add('orderBy', 'e.ville ASC')
                ;
            },
        ));

        //some other fields here...
    }

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

2 个答案:

答案 0 :(得分:2)

我终于设法使用表单事件找到解决方案。我在http://symfony.com/doc/current/cookbook/form/dynamic_form_generation.html玩了“教程”,并且开始工作了:)下面是我用过的代码,如果有人感兴趣的话。

我的formType:

<?php
//src/Auth/UserBundle/Form/Type/RegistrationFormType.php
namespace Auth\UserBundle\Form\Type;

use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use Doctrine\ORM\EntityRepository;
use Auth\GeoBundle\Form\LocalisationType;

use Auth\UserBundle\Form\EventListener\IsAdminFieldSubscriber;

class RegistrationFormType extends BaseType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        //NE PAS EFFACER -> exempled e comment ajouter un champ qui n'a rien à voir avec nos entitys
        //$builder->add("firstName", "text", array("mapped" => false));

        $builder->add('departement', 'genemu_jqueryselect2_entity', array(
            'mapped' => false,
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'departement',
            'query_builder' => function ($repository) {
                return $repository
                    ->createQueryBuilder('e')
                    ->add('groupBy', 'e.departement')
                ;
            },
        ));


        $dpt = "";
        $builder->add('localisation', 'genemu_jqueryselect2_entity', array(
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'formLabel',
            'query_builder' => function ($repository) use ($dpt) {
                return $repository
                    ->createQueryBuilder('e')
                    ->where('e.departement = :dpt')
                    ->setParameter('dpt', $dpt)
                    ->add('orderBy', 'e.ville ASC')
                ;
            },
        ));

        $builder->add('sexe', 'genemu_jqueryselect2_choice', array(
            'empty_value' => '',
            'choices'   => array(
                'homme'   => 'Homme',
                'femme' => 'Femme',
            ),
            'configs' => array(
                'minimumResultsForSearch' => 5,
            )
        ));

        $builder->add('date_naissance', 'date', array(
            'empty_value' => '',
            'widget' => 'choice',
            'attr' => array('class' => 'input-small'),
            'years' => range(1900,2100),
            'months' => range(1,12),
            'days' => range(1,31),
        ));

        $builder->add('petit_mot');

        $subscriber = new IsAdminFieldSubscriber($builder->getFormFactory());
        $builder->addEventSubscriber($subscriber);
    }


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

我的EventListener:

<?php
//src/Auth/UserBundle/Form/EventListener/isAdminFieldSubscriber.php
namespace Auth\UserBundle\Form\EventListener;

use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;

class IsAdminFieldSubscriber implements EventSubscriberInterface
{
    /**
     * @var FormFactoryInterface 
     */
    private $factory;

    /**
     * @param FormFactoryInterface $factory 
     */
    public function __construct(FormFactoryInterface $factory)
    {
        $this->factory = $factory;
    }

    /**
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return array(
            FormEvents::PRE_BIND => 'preBind',
        );
    }

    /**
     * Called before form data is set
     *
     * @param DataEvent $event
     */
    public function preBind(DataEvent $event)
    {
        $data = $event->getData();
        $form = $event->getForm();

        if (null === $data) {
            return;
        }

        $dpt = $data['localisation'];

        $form->add($this->factory->createNamed('localisation', 'entity', null, array(
            'empty_value' => '',
            'class' => 'AuthGeoBundle:Localisation',
            'property' => 'formLabel',
            'query_builder' => function ($repository) use ($dpt)  {
                return $repository
                    ->createQueryBuilder('e')
                    ->where('e.id = :dpt_id')
                    ->setParameter('dpt_id', $dpt)
                    ->add('orderBy', 'e.ville ASC')
                ;
            },
        )));
    }

}

答案 1 :(得分:0)

您自己解释问题:

  

“这是因为提交的值不包含在查询构建器返回的”数组“中。”

您可以使用data transformers来解决此问题。

相关问题