【问题标题】:How to create dynamic cascade form in Symfony?如何在 Symfony 中创建动态级联形式?
【发布时间】:2018-01-16 23:59:44
【问题描述】:

我使用 Symfony 3 已经有一段时间了,直到现在我只生成简单的表单。现在,我想生成一个更复杂、更动态的表单,希望能得到一些帮助。

我的网站引用了与类别相关联的产品。因此,我创建了一个依赖于 Doctrine 扩展 TreeProductCategory 实体。因此,实际产品是树结构的叶子,其他节点(即至少有一个孩子的节点)只是产品类别。

这种结构的一个例子是这个:

Food
      Fruits
           Apple
           Pear
      Vegetables
           Pepper
           Zucchini
 Vehicle
      Car
      Bike

在本例中,产品是 Apple、Pear、Pepper、Zucchini、Car 和 Bike。

我想生成一个用于选择产品的表单。预期的行为是这样的:

  • 最初,用户会看到一个包含根类别(此处为食物和车辆)的下拉列表
  • 当用户选择一个类别时,前一个下拉列表下方会出现一个新的下拉列表,其中填充了与先前选择的类别相对应的子类别(例如,如果选择了食物,则为水果和蔬菜)
  • 在用户选择产品(即树形结构的一个叶子)之前,此过程应该是可重复的。

为了使表单有效,用户必须选择一个产品(叶子)。

目前,我已经能够生成带有列出根类别的下拉列表的初始表单。这是用于执行此操作的代码。

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use AppBundle\Entity\ProductCategory;
use AppBundle\Repository\ProductCategoryRepository;
 
class ProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
            $builder->add('productCategory',EntityType::class,array(
                'class'         => 'AppBundle:ProductCategory',
                'query_builder' => function(ProductCategoryRepository $repository){
                        return $repository->getRootNodesQueryBuilder();
                },
                'label'         => 'product category',
                'choice_label'  => 'name',
                'choice_value'  => 'name',
                'multiple'      => false,
                'expanded'      => false,
                'required'      => true
            ));
    }
 
 
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Product::class,
            'method' => 'POST',
        ));
    }
}

由此,我们的想法是使用 AJAX 和 jQuery 来:

  • 使用下拉菜单中的“更改”事件将(当前)选择的类别发送到服务器
  • 在前一个下拉列表下方生成并显示新的下拉列表,并带有足够的

但是,我不知道如何修改 ProductType 类以便根据当前选择的类别生成新的 EntityType 字段,然后发回更新的表单以允许其通过 jQuery 显示。

因此,我们非常欢迎任何帮助或建议,以便在构建这种动态表单方面取得进展!

【问题讨论】:

标签: forms symfony dynamic symfony-forms


【解决方案1】:

如果我正确理解您的问题,那么您需要获取给定类别的子类别。您可以将其作为选项传递给ProductType

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use AppBundle\Entity\ProductCategory;
use AppBundle\Repository\ProductCategoryRepository;
 
class ProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
            $category = $options['category'];

            $builder->add('productCategory',EntityType::class,array(
                'class'         => 'AppBundle:ProductCategory',
                'query_builder' => function(ProductCategoryRepository $repository) use ($category){
                        return $repository->getRootNodesQueryBuilder($category);
                },
                'label'         => 'product category',
                'choice_label'  => 'name',
                'choice_value'  => 'name',
                'multiple'      => false,
                'expanded'      => false,
                'required'      => true
            ));
    }
 
 
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Product::class,
            'method' => 'POST',
            'category' => null
        ));
    }
}

getRootNodesQueryBuilder() 中,您可以根据传递的类别解析子类别。在控制器中(您收到 AJAX 请求的地方),您可以像使用它一样

$form = $this->createForm(ProductType::class, $product, [
        'category' => $request->get('category')
]);

【讨论】:

  • 谢谢你的帮助,我这就走。但是:我的控制器有一个问题:如何检测表单是否已完全提交(也通过 AJAX 完成),或者是否只发送了部分数据(即新选择的类别)?如果可能的话,我想在这两种情况下使用相同的控制器。
  • 我建议不要提交部分数据。您可以改为在 ajax 数据中发布此字段值并获取请求。因此,您不必担心部分或全部数据。如果你真的需要检查,你可以检查其他字段是否在发布数据中
  • 将 ajax 中的单个字段发布到控制器的问题是 $form->handleRequest($request) 会引发错误,因为我猜它期望所有字段的数据(不仅通过 ajax 发送的类别)。在已发布单个字段的情况下,我想我不必使用 handleRequest 方法......但在这种情况下,我不知道如何更新表单,因为未提交表单(并且更新基于在 POST_SUBMIT 事件中...)。
猜你喜欢
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多