Search code examples
phpsymfonysymfony-formsformcollection

symfony 2 create dynamic radio fields collection


I'm working with Symfony 2 forms. As part of the project I want to create radio field collection. Please see my code structure below,

Controller

$gridElements = array(
    array(
        'field_name' => 'grid_qd_1',
        'field_label' => '1. Difficulty in Opening a tight or new jar',
        'section_header' => "Grid 1"
    ),
    array(
        'field_name' => 'grid_qd_2',
        'field_label' => '2. Do heavy household chores (e.g., wash walls, floors)',
        'section_header' => "Grid 1"
    ),
    array(
        'field_name' => 'grid_qd_3',
        'field_label' => '3. Carry a shopping bag or briefcase',
        'section_header' => "Grid 1"
    ),
    array(
        'field_name' => 'grid_qd_4',
        'field_label' => '4. Use a knife to cut food',
        'section_header' => "Grid 1"
    )
);
$form = $this->createForm(new GridType($gridElements));

MyBundle/Form/Type/GridType.php

class GridType extends AbstractType
{
    public function __construct($gridData)
    {
        $this->gridData = $gridData;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add("grid", CollectionType::class, array(
            "label" => "Main Grid",
            'attr' => array(
                'has_branching' => 1,
                "branching_logic" => 0,
                "section_header" => $this->gridData[0]['section_header']
            )
        ));

        foreach ($this->gridData as $key => $data) {
            $builder->get("grid")->add('radio_'.$key, new GridItemType($data));
        }

    }
}

MyBundle/Form/Type/GridItemType.php

class GridItemType extends AbstractType
{
    private $gridItem;

    public function __construct($gridItem = array()) {
        $this->gridItem = $gridItem;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('item', ChoiceType::class, array(
            "label" => $this->gridItem['field_label'],
            'choices' => array(
                '3' => '3',
                '4' => '4',
                '5' => '5',
            ),
            'expanded' => true,
            'multiple' => false,
            'attr' => array(
                'has_branching' => 1,
                "branching_logic" => 0,
                "section_header" => $this->gridItem['section_header']
            )

        ));

        if (!is_null($this->gridItem)){
            $builder->setData($this->gridItem);
        }
    }
}

When I tried to render the form, I'm getting only the collection field, child fields under the collection is not getting displayed.

I'm using twig, and I tried to loop through form but nothing is coming up except the collection field.

Where I went wrong?


Solution

  • For some reason i wasn't able to add children in the parent's formType build method, but this is how i got it to work.

    GridType

    class GridType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder->add('grid', CollectionType::class, array(
                'label' => 'Main Grid',
                'entry_type' => GridItemType::class,
                'attr' => array(
                    'has_branching' => 1,
                    'branching_logic' => 0,
                    'section_header' => 'Main',
                )
            ));
        }
    
        public function getName()
        {
            return 'grid_type';
        }
    }
    

    GridItemType

    class GridItemType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder->add('item', ChoiceType::class, array(
                "label" => $options['field_label'],
                'choices' => array(
                    '3' => '3',
                    '4' => '4',
                    '5' => '5',
                ),
                'expanded' => true,
                'multiple' => false,
                'attr' => array(
                    'has_branching' => 1,
                    "branching_logic" => 0,
                    "section_header" => $options['section_header']
                )
            ));
        }
    
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setRequired([
                'field_name', 'field_label', 'section_header'
            ]);
    
            $resolver->setDefaults([
                'auto_initialize' => false
            ]);
        }
    
        public function getName()
        {
            return 'grid_item_type';
        }
    }
    

    Action

    $gridElements = array(
                array(
                    'field_name' => 'grid_qd_1',
                    'field_label' => '1. Difficulty in Opening a tight or new jar',
                    'section_header' => "Grid 1"
                ),
                array(
                    'field_name' => 'grid_qd_2',
                    'field_label' => '2. Do heavy household chores (e.g., wash walls, floors)',
                    'section_header' => "Grid 1"
                ),
                array(
                    'field_name' => 'grid_qd_3',
                    'field_label' => '3. Carry a shopping bag or briefcase',
                    'section_header' => "Grid 1"
                ),
                array(
                    'field_name' => 'grid_qd_4',
                    'field_label' => '4. Use a knife to cut food',
                    'section_header' => "Grid 1"
                )
            );
    
            $form = $this->createForm(GridType::class, null);
    
            foreach ($gridElements as $key => $gridElement) {
                $form->get('grid')->add(
                    $this->get('form.factory')
                        ->createNamed('radio_' . $key, GridItemType::class, null, $gridElement)
                );
            }