Symfony2表单问题,添加动态字段

时间:2015-07-11 17:15:48

标签: symfony

我有一个描述包的symfony 2表单:

class PackageType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->setMethod('POST')
            ->add('deliveryNote')
            ->add('receiver', new ReceiverType());

        // field stockitem exists, added dynamically NOT good

    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'IREnterprise\AppBundle\Entity\Package',
            'csrf_protection'   => false,
            'allow_extra_fields' => true
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'IREnterprise_AppBundle_package';
    }
}

每个包都有1个接收器,以及与包关联的动态数量的包行,每个包行包含一个stockitem。

这个想法是用户能够添加现有的StockItems作为包装线。

我已经实现了,它看起来像这样: enter image description here 每次用户单击addPackageLine时,都会将一个包行添加到表单中,并且他可以选择一个stockItem和该stockItem的数量。

无论如何,我不得不做一些破坏性的事情来绕过formBuilder。

所以控制器最终看起来像这样:

public function newPackageAction(Request $request)
{
    $package = new Package();
    $form = $this->createForm(new PackageType(), $package);
    $form->handleRequest($request);

    // Test if stock item belongs to user, and add to package
    $formStockItems = $request->request->get('IREnterprise_AppBundle_package[stockItems]', null, true);

    // This is bad ... very bad, should be a doctrine validation
    if (empty($formStockItems)) {
        $form->add('packageLines')->addError(new FormError('Package Lines cannot be null'));
    }


    if ($form->isValid()) {

        $em = $this->getDoctrine()->getManager();

        $package->setUser($this->getUser());

        foreach ($formStockItems as $formStockItem) {
            $stockItem = $em->getRepository('IREnterpriseAppBundle:StockItem')
                ->findByUserAndId($this->getUser(), $formStockItem['item']);

            if (!empty($stockItem)) {

                // Create a package line for the stock item, and add it the line to the package
                $packageLine = new PackageLine();
                $packageLine->setStockItem($stockItem);
                $packageLine->setAmount($formStockItem['quantity']);
                $packageLine->setPackage($package);

                $package->addPackageLine($packageLine);
            }
        }

        $em->persist($package);
        $em->flush();

        $response = View::create($package);
        return $response;
    }

    return View::create($form, Response::HTTP_BAD_REQUEST);

}

我想以一种不那么强硬的方式做到这一点,所以form-> isValid()也验证了所有发送的packageLiens,因为我的表单错误搞砸了这种方法,有什么建议吗?

1 个答案:

答案 0 :(得分:1)

在交响乐中使用“集合”表单类型。有关完整的详细信息,请参阅How to Embed a Collection of Forms文档,但基本原则是集合类型采用选项“type”,它指定集合中每个元素的表单类型。

您还可以指定“allow_add”和“allow_delete”选项以允许其动态调整大小。

使用“allow_add”还可以创建一种“原型”表单字段,javascript可以使用该字段为此集合中的新项目呈现表单