7
votes

I'm trying to implement dynamic forms in Symfony2. The form is simple, first the user selects a broker, and then select an account according to that broker. Therefore, the account is disabled until the broker is selected.

In case of a text input, read_only => true could be a solution, but select has no attribute readonly. So, I made the select disabled, and then tried to enable the select with jQuery:

$('#form select').prop('disabled', false);

The problem is that on the server side, Symfony cannot handle the disabled form field. Its value is simply set to null.

I thought of possible solutions. First of all, I could manually set the field value in the controller, because I tested that the form field value is actually in the request parameter, Symfony just ignores to handle it and map it to the object. I think it would work, however it's not really nice solution.

Secondly, I can disable the select with some client side hacking, or add a hidden input to the form and manually set the value of it with Javascript.

Is there a standard solution here?

My form entity looks like this:

$builder->add('broker', 'entity', array(
    'class'         => 'MyBundle:Broker',
    'property'      => 'name',
    'query_builder' => function(BrokerRepository $br) {
                           return $br->getActiveBrokersQuery();
                       },
    'required'      => true,
    'empty_value'   => 'Choose a broker',
));

$builder->add('accountType', 'entity', array(
    'class'       => 'MyBundle:AccountType',
    'empty_value' => 'Choose a broker first',
    'disabled'    => true,
));

If I do not disable the select, everything works fine, Symfony handles the request perfectly.

1
Fire up a step-debugger and take a look why Symfony does not handle that element and it's value is NULL. Is it truly NULL or just not set because the browser does not send the element? As the code is all open, you should profit from that. Best practices are available in the Symfony2 Cookbook.hakre
If I call $accountAddForm->handleRequest($request);, I get this for $accountAddForm->getData(): object(stdClass)#653 (6) { ["__CLASS__"]=> string(42) "CashbackCloud\FcbcBundle\Entity\AccountAdd" ["broker"]=> object(stdClass)#764 (19) { ["__CLASS__"]=> string(38) "CashbackCloud\FcbcBundle\Entity\Broker" ["id"]=> int(8) ... } ["id"]=> NULL ["user"]=> NULL ["accountType"]=> NULL ["accountName"]=> string(4) "3232" }omgitsdrobinoha
But if I call $request->request->all() after submitting the form. I get the following: array(1) { ["AccountAdd"]=> array(5) { ["broker"]=> string(1) "8" ["accountType"]=> string(2) "54" ["accountName"]=> string(4) "3232" ["save"]=> string(0) "" ["_token"]=> string(40) "b3b118149c1dd7a0f861b0c81d147522d5a3d87f" } } So the value is actually in the request, but symfony just doesn't map it into the object. I think because of the disabled value. Am I right?omgitsdrobinoha
Okay, so you're one step further. Now you have to tell with that request Symfony the condition that the form element is not disabled any longer as so far in your definition (configuration) it is still disabled. (and your nickname all uppercase is not very friendly to read, just saying.)hakre
So my nickname is why people never answer my questions. :) I found a solution based on your suggestions. I will submit it in the near future. :) Thanks!omgitsdrobinoha

1 Answers

7
votes

I managed to solve the problem, based on hakre's suggestions. So I needed to tell the form that the field is not disabled any more. Thus, I added a PRE_SUBMIT event to the form, in which i set the disabled value to false on the accountType field.

$builder->addEventListener(
            FormEvents::PRE_SUBMIT,
            function(FormEvent $event) {
                $event->getForm()->add('accountType', 'entity', array(
                    'class' => 'XXBundle:AccountType',
                    'empty_value' => 'Choose a broker first',
                    'disabled' => false
                ));
            }
        );

Thanks for your suggestions!