Symfony2 表单事件 - 下拉列表 [英] Symfony2 Form Events - Drop down lists

查看:22
本文介绍了Symfony2 表单事件 - 下拉列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Symfony2 网站中,我正在尝试制作一个包含 2 个(或 3 个)下拉列表的表单,其中包含像 Country > Region > City 这样的依赖项.那个城市是我正在用表单编辑的元素的一个字段.这个想法是根据选择填充列表.

In a Symfony2 website I'm trying to make a form with 2 (or 3) dropdown lists with a dependency like Country > Region > City. And that city is a field of the element I'm editing with the form. The idea is to fill the lists depending on selections.

我已经按照此处的表单事件教程进行了操作:http://autic.16mb.com/wordpress/2011/08/symfony2-dynamic-forms-an-event-driven-approach/(基于 webb-on-the-web .com/?p=5)

I've followed the tutorial with form events here : http://aulatic.16mb.com/wordpress/2011/08/symfony2-dynamic-forms-an-event-driven-approach/ (which is based on webb-on-the-web .com/?p=5)

我遇到的问题:一切正常,但是当我使用表单编辑元素时,正确选择了城市(从数据库中),但国家和地区下拉列表已预先填充并保留在选择值"上.我不知道它是否应该与教程一起使用.

The issue I have: it all works but when I use the form to edit the element, the city is selected correctly (from DB) but the Country and Region dropdown lists are prefilled and left on 'select a value'. I don't know if it was supposed to work with the tutorial as it is.

问题:如何选择这些列表?我正在尝试添加 POST_SET_DATA 事件,但找不到在表单字段中选择值的方法.

The question : how can I make these lists selected? I'm trying to add a POST_SET_DATA event but I can't find a way to select the value in the form field.

这是表单类:http://pastebin.com/PpWkHxC3(请注意,它不是城市,而是:字段 > 主题和主题是表单编辑的课程的字段).

Here's the form class : http://pastebin.com/PpWkHxC3 (note that instead of city it's : Field > Topic and topic is a field of a Lesson which the form edits).

推荐答案

我差点就搞定了.如果其他人需要这个,那么在编辑现有项目时需要添加什么才能使此解决方案完美运行:

I almost had it. If anybody else ever needs this here's what needs to be added to make this solution work perfectly when editing an existing item :

class ItemDetailForm extends AbstractType
{
   ...
        $builder->addEventListener(FormEvents::POST_SET_DATA, function (DataEvent $event) use ($refreshTopic) {
            $data = $event->getData();
            $form = $event->getForm();
            if (null === $data) {
                return;
            }

            $form->get('region')->setData($data->getCity()->getRegion());
        });
}

自 symfony 2.1 起,POST_SET_DATA 事件在子项添加到表单之前被调用,导致所有 get('region') 引发异常.解决方案是在 POST_SET_DATA 中创建此字段,而不是在 buildForm() 中:

since symfony 2.1, the POST_SET_DATA event is called before the children are added to the form, causing all the get('region') to raise an exception. The solution is to create this field in the POST_SET_DATA and not in the buildForm() :

        /** @var FormFactory $factory */
        $form->add($factory->createNamed('region', 'entity', null, array(
            'class'=>'AcmeBundle:Region',
            'property_path'=>false,
            'empty_value'=>'Choose a value',
            'required'=>true,
            'label'=>'Region'
        )));

请注意,您需要将 $factory 添加到处理事件的闭包的使用"中:

Note that you need to add the $factory to the 'use' of the closure handling the event :

$builder->addEventListener(FormEvents::POST_SET_DATA, function (DataEvent $event) use ($refreshTopic, $factory) {

这是整个表单类:

<?php
namespace AAA\CoreBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Form;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EntityRepository;
use AAA\CoreBundle\Entity\ClassYear;
use AAA\CoreBundle\Entity\Field;
use AAA\CoreBundle\Entity\Lesson;
use AAA\CoreBundle\Form\LessonContentForm;

class LessonDetailForm extends AbstractType
{
    public $country;
    function __construct($country=null) {
        // Get country for classyear dropdown list
        $this->country = $country;
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $factory = $builder->getFormFactory();

        $builder->add('name', null, array('label'=>'Titre de la leçon'));
        $builder->add('description', 'textarea', array('label'=>'Description (définition conceptuelle) Qu\'est-ce que c\'est ? Et à quoi ça sert ? (importance, utilité)'));
        $builder->add('text', 'textarea', array('label'=>'Leçon', 'required'=>false)); // Can't set 'required' on textareas used by TinyMCE
        $builder->add('reperes', 'textarea', array('label'=>'Repères (détectionel) - Quels sont les éléments qui me permettent de repérer que je dois penser à ce concept ?', 'required'=>false));
        $builder->add('other_topic', null, array(
            'required'  =>  false,
            'mapped'     =>  false
        ));

        $refreshField = function ($form, $classyear) use ($factory) {
            /** @var FormFactory $factory */
            /** @var Form $form */
            $form->add($factory->createNamed('field','entity',null, array(
                'class'         => 'AAA\CoreBundle\Entity\Field',
                'mapped'        => false,
                'label'         => 'Matière',
                'empty_value'   => 'Sélectionne une valeur',
                'empty_data'    => null,
                'required'      => false,
                'query_builder' => function (EntityRepository $repository) use ($classyear) {
                    $qb = $repository->createQueryBuilder('field')
                        ->innerJoin('field.classyear', 'classyear');

                    if($classyear instanceof ClassYear) {
                        $qb = $qb->where('field.classyear = :classyear')
                            ->setParameter('classyear', $classyear);
                    } elseif(is_numeric($classyear)) {
                        $qb = $qb->where('classyear.id = :classyear_id')
                            ->setParameter('classyear_id', $classyear);
                    } else {
                        $qb = $qb->where('0 = 1');
                    }

                    return $qb;
                }
            )));
        };
        $refreshTopic = function ($form, $field) use ($factory) {
            /** @var FormFactory $factory */
            /** @var Form $form */
            $form->add($factory->createNamed('topic','entity',null, array(
                'class'         => 'AAA\CoreBundle\Entity\Topic',
                'property'      => 'name',
                'label'         => 'Sujet',
                'empty_value'   => 'Sélectionne une valeur',
                'empty_data'    => null,
                'required'      => false,
                'query_builder' => function (EntityRepository $repository) use ($field) {
                    $qb = $repository->createQueryBuilder('topic')
                        ->innerJoin('topic.field', 'field');

                    if($field instanceof Field) {
                        $qb = $qb->where('topic.field = :field')
                            ->setParameter('field', $field);
                    } elseif(is_numeric($field)) {
                        $qb = $qb->where('field.id = :field_id')
                            ->setParameter('field_id', $field);
                    } else {
                        $qb = $qb->where('0 = 1');
                    }

                    return $qb;
                }
            )));
        };

        // Populate ddl to show form
        $country = $this->country;
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($refreshTopic, $refreshField, $factory, $country) {
            /** @var Lesson $data */
            $data = $event->getData();
            $form = $event->getForm();

            // Test if null because this event is called 2 times, only the second time with the actual Lesson object (which has null values in the creation case)
            if($data != null)
                // In case of creation
                if($data->getId()==null) {
                    // Creates empty fields
                    $refreshTopic($form, null);
                    $refreshField($form, null);
                }
                // In case of edition
                else {
                    if ($data->getTopic() != null) {
                        $refreshTopic($form, $data->getTopic()->getField());
                        if ($data->getTopic()->getField() != null) {
                            $refreshField($form, $data->getTopic()->getField()->getClassYear());
                        }
                    }
                    else {
                        $refreshField($form, null);
                        $refreshTopic($form, null);
                    }
                }

            /** @var FormFactory $factory */
            $form->add($factory->createNamed('classyear', 'entity', null, array(
                'class'         => 'AAACoreBundle:ClassYear',
                'property'      => 'name'.$country,
                'mapped'        => false,
                'label'         => 'Année',
                'empty_value'   => 'Sélectionne une valeur',
                'empty_data'    => null,
                'required'      => false,
                'query_builder' => function (EntityRepository $repository) {
                    return $repository->createQueryBuilder('classyear')
                        ->orderBy('classyear.sort');
                }
            )));
        });
        // Populate ddl when form was posted
        $builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) use ($refreshTopic, $refreshField) {
            $form = $event->getForm();
            $data = $event->getData();

            if(array_key_exists('classyear', $data)) {
                $refreshField($form, $data['classyear']);
            }
            if(array_key_exists('field', $data)) {
                $refreshTopic($form, $data['field']);
            }
        });

        // Select value in ddl when editing
        $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) use ($refreshTopic) {
            /** @var Lesson $data */
            $data = $event->getData();
            $form = $event->getForm();
            if (null === $data || null === $data->getId() ) {
                return;
            }

            if ($data->getTopic() != null) {
                $form->get('field')->setData($data->getTopic()->getField());
                if ($data->getTopic()->getField() != null) {
                    $form->get('classyear')->setData($data->getTopic()->getField()->getClassYear());
                }
            }
        });
    }
    public function getName()
    {
        return 'LessonDetailForm';
    }
    /** @param OptionsResolverInterface $resolver */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AAA\CoreBundle\Entity\Lesson'
        ));
    }
}

?>

这篇关于Symfony2 表单事件 - 下拉列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆