Longbow4685
Longbow4685

Reputation: 23

How to create dynamic cascade form in Symfony?

I have been using Symfony 3 for a while, and until now I only generated simple forms. Now, I would like to generate a more complex, dynamic form and a bit of help would be appreciated.

My website references Products, that are associated to categories. Therefore, I created a ProductCategory entity which relies on the Doctrine extension Tree. The actual products are therefore the leaves of the tree structure, the other nodes (i.e. those with at least one child) are only product categories.

An example of such structure would be this one:

Food
      Fruits
           Apple
           Pear
      Vegetables
           Pepper
           Zucchini
 Vehicle
      Car
      Bike

In this example, the products are Apple, Pear, Pepper, Zucchini, Car and Bike.

I would like to generate a form aimed at selecting a product. The expected behavior would be this one:

In order for the form to be valid, the user must have selected a Product (leaf).

For now, I have been able to generate the initial form with the dropdown listing the root categories. Here is the code used to do this.

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',
        ));
    }
}

From this, the idea would be to use AJAX and jQuery to:

However, I do not know how to modify the ProductType class in order to generate the new EntityType field based on the current selected category, then to send back the updated form in order to allow its display by jQuery.

Therefore, any help or advice would be more than welcome in order to make progress in building this dynamic form !

Upvotes: 1

Views: 769

Answers (1)

hanish singla
hanish singla

Reputation: 792

If I understand your problem correctly then you need to get child categories for given categories. You can pass it as a option to 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
        ));
    }
}

In getRootNodesQueryBuilder() you can parse child categories based upon passed category. In controller (where you receive AJAX request), you can use it like

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

Upvotes: 1

Related Questions