1
votes

In the Entity controller, the create and edit use the same formType, this then has a definition for a field which is a relation to a collection of Entities. The issue I am having is that I cannot find a way to pass in the $options array into the form builder which would then be available to the sub entity formType. I could pass all the values through the constructors of the formTypes but this feels to be a workaround not a solution.

My controller example (state is the additional option i wish to pass through);

private function createEditForm(Delivery $entity)
{
    $form = $this->createForm(new DeliveryType(), $entity, array(
        'state'=>'update', // This is the extra value I wish to pass through.
        'action' => $this->generateUrl('delivery_update', array('id' => $entity->getId())),
        'method' => 'PUT',
    ));
    $form->add('submit', 'submit', array('label' => 'Update'));
    return $form;
}

and in the form builder class I've included it into the setDefaultOptions() like so

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'Acme\DemoBundle\Entity\Delivery',
        'state' => 'create'

    ));
}

but in this formType class I cannot find a way to pass it into the collection of entities without using the constructor of the collection formType. My main formType class looks like this;

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('date', 'date', array(
                'widget' => 'single_text',
                'datepicker' => true
        ))
        ->add('poNumber')
        ->add('deliveryItems', 'collection', array(
            'type'         => new DeliveryItemType($id),
            'allow_add'    => true,
            'allow_delete' => true,
            'prototype'    => true,
            'by_reference' => false,
        ))
    ;
}

and the sub entity formType looks like this;

public function buildForm(FormBuilderInterface $builder, array $options)
{

    $builder
        ->add('stock', 'entity', array(
            'class' => 'Acme\DemoBundle\Entity\Stock',
            'attr'   =>  array(
                'class'   => 'chosen'
            )
        ))
        ->add('quantity')
    ;
}

The reason I am trying to specify the difference between the update and create is so I do not have to duplicate the formType class files with just a single line change to each. Passing the value through the constructors will work but it's not clean or maintainable. Another possible option is doing this through Twig but I feel that manually outputting the form widgets a step backwards.

My ideal solution would be to give the sub-entity fields a custom status (disabled) on the edit Controller/page so that the relations cannot be reset once it was created as this would cause problems in my code.

I've also looked into Form EventListeners but this is post/pre submit and gives access to the data, I could not force the output of a field to be disabled on the edit page only.

1

1 Answers

2
votes

The issue was that in the DeliveryType class I couldn't work out how to pass options into the sub formType. The information here: http://symfony.com/doc/current/reference/forms/types/collection.html#basic-usage and some help in IRC cleared up what I was missing.

My main formType now has an extra line in the entity collection definition;

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('date', 'date', array(
                'widget' => 'single_text',
                'datepicker' => true
        ))
        ->add('poNumber')
        ->add('deliveryItems', 'collection', array(
            'type'         => new DeliveryItemType($id),
            'allow_add'    => true,
            'allow_delete' => true,
            'prototype'    => true,
            'by_reference' => false,
            'options' => array('state' => $options['state']), // THIS LINE!
        ))
    ;
}

Which then means I can call the $options array in the sub formType (ensure both formTypes have the setDefaultOptions function with the name of the option)