Symfony 2.7:从表单生成器中自动填充表单域

时间:2015-12-22 00:49:04

标签: symfony symfony-forms

我有一个名为HoursSpecial的实体,它与一个名为HoursArea的实体具有外键关系。每个HoursSpecial属于HoursArea。当我通过我的HoursSpecialType创建一个新的HoursSpecial时,我希望表单字段自动填充HoursArea字段。

我知道你在想什么,只是在我的控制器方法中做这样的事情:

$form->add('area', 'hidden', array('data'=>$area));

除非我需要让DataTransformer在区域ID和实际区域实体之间切换,否则这样会很好。所以我必须使用变换器在HoursSpecialType中声明我的HoursArea字段:

    $builder
        ...
        ->add('area', 'hidden')
    ;

    $builder->get('area')->addModelTransformer(new HoursAreaToIntTransformer($this->manager));

现在,我无法简单地将HoursArea实体提供给表单。有没有一种有效的方法来实现这一目标?

我已经在How to Dynamically Modify Forms Using Form Events上翻阅了Symfony的文档,但是我无法从表单构建器外部动态传递那个HoursArea实体。 。也许我只是错过了一些东西?

更新

根据以下@Ryan的答案(建议#1)的建议,我创建了自定义类型HiddenHoursAreaType:

// AppBundle\Form\Type\HideenHoursAreaType.php
class HiddenHoursAreaType extends AbstractType
{
//need to instantiate HoursAreaToIntTransformer
private $manager;

public function __construct(ObjectManager $manager)
{
    $this->manager = $manager;
}

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $transformer = new HoursAreaToIntTransformer($this->manager);
    $builder->addModelTransformer($transformer);
}



public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => null,
        'compound' => true  //this should be FALSE as there are no children
    ));
}

/**
 * 
 * the return value of the getParent function indicates that you're extending the choice field type. 
 * This means that, by default, you inherit all of the logic and rendering of that field type.
 */
public function getParent()
{
    return 'hidden';
}

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

我已将变换器添加到自定义类型类中。这是变压器类:

// AppBundle\Form\DataTransformer;
class HoursAreaToIntTransformer implements DataTransformerInterface
{
    private $manager;

    public function __construct(ObjectManager $manager)
    {
        $this->manager = $manager;
    }

    /**
     * Transforms an object (HoursArea) to a string (number).
     *
     * @param  Issue|null $issue
     * @return string
     */
    public function transform($area)
    {
        if (null === $area) {
            return '';
        }

        return $area->getId();
    }

    /**
     * Transforms a string (number) to an object (HoursArea).
     *
     * @param  string $areaId
     * @return HoursArea|null
     * @throws TransformationFailedException if object (HoursArea) is not found.
     */
    public function reverseTransform($areaId)
    {
        // no area number? It's optional, so that's ok
        if (!$areaId) {
            return;
        }

        $area = $this->manager
            ->getRepository('AppBundle:HoursArea')
            // query for the issue with this id
            ->find($areaId)
        ;

        if (null === $area) {
            // causes a validation error
            // this message is not shown to the user
            // see the invalid_message option
            throw new TransformationFailedException(sprintf(
                'An area with number "%s" does not exist!',
                $areaId
            ));
        }

        return $area;
    }
}

在我的控制器中,我使用自定义类型字段创建表单:

$form = $this->createForm(new HoursSpecialType($this->getDoctrine()->getManager()), $entity, array(
        'action' => $this->generateUrl('hoursspecial_postcreate'),
        'method' => 'POST',
    ));
    $form->add('eventDate', 'hidden', array('data'=>$dateString));
    $form->add('area', new \AppBundle\Form\Type\HiddenHoursAreaType($this->getDoctrine()->getManager()), array(
        'data'=>$area,
        'invalid_message'=>'Area field not converted proerly'
    ));

    $form->add('submit', 'submit', array('label' => 'Create'));

由于变换器和自定义类型,表单现在可以正确地将HoursArea实体转换为隐藏字段中填充的整数。

现在的问题是,在表单提交时,整数不会转换回HoursArea对象。我知道这是因为我得到了' invalid_message'提交后。

最终更新

未正确插入HoursArea ID的原因与

有关
'compound' => true

我的自定义类型设置。我认为它正在寻找儿童田地,并没有找到任何......它不应该没有,因为没有!

1 个答案:

答案 0 :(得分:2)

  1. 您可以为其创建自定义类型,并在自定义类型的addModelTransformer()中添加buildForm()调用,但仍会显式传递数据。因此,$form->add('area', 'hidden', array('data'=>$area))将成为$form->add('area', new HiddenHoursAreaType(), array('data'=>$area)),其中HiddenHoursAreaType::getParent()将是hidden类型。

  2. 您可以在POST_SET_DATA监听器中设置数据。

  3. 您可以在$options['data']中获取buildForm()值并明确传入HoursArea ID。

    /** @var HoursSpecial $hoursSpecial Prepopulated in controller */
    $hoursSpecial = $options['data']
    $builder->add('area', 'hidden', ['data' => $hoursSpecial->getHoursArea()->getId()])