How to set default value or option in the Symfony embedded form inside the Action

Janusz Slota - Mon 26 September 2011 - embedded-forms, forms, php, symfony1

Let's say you have Symfony 1.4 form User with embedded form Entry

<?php

class EntryForm extends BaseEntryForm
{
  public function configure()
  {
    $this->widgetSchema['cars'] = new sfWidgetFormChoice(array(
      'choices' => array(),
      'expanded' => true
    ));
    $this->validatorSchema['cars'] = new sfValidatorChoice(array(
      'choices' => array()
    ));
  }
}

and let's say that this embedded form contains sfWidgetFormChoice widget

Mind that choices option is an empty array - I want to set this option in the action as it depends on data in the session.

I found that, the following code in the action layer doesn't work:

<?php

class defaultActions extends sfActions
{
  public function executeIndex(sfWebRequest $request)
  {
    $this->form = new UserForm();
    $this->form->getEmbeddedForm('entry')
      ->getWidget('cars')
      ->setOption('choices', $this->getUser()->getAttribute('cars'));
  }
}

Not sure why, but it'd work if the cars widget is attached to the UserForm. Maybe it's related to this bug. Anyway, if try to set option choices, it sets correctly, but the view layer ignores it.

<?php

class defaultActions extends sfActions
{
  public function executeIndex(sfWebRequest $request)
  {
    $this->form = new UserForm();
    $this->form->getEmbeddedForm('entry')
      ->getWidget('cars')
      ->setOption('choices', $this->getUser()->getAttribute('cars'));

    if($this->form
      ->getEmbeddedForm('entry')
      ->getWidget('cars')
      ->getOption('choices') == $this->getUser()->getAttribute('cars'))
    {
      throw new Exception('setting up options for embedded forms works correctly,
        but the view layer seems to ignore it.');
    }
  }
}

So, if you have trouble setting up the dynamic options for the embedded form, you can do this, which seems to work.

<?php

class defaultActions extends sfActions
{
  public function executeIndex(sfWebRequest $request)
  {
    $this->form = new UserForm();
    $this->form['entry']['cars']
      ->getWidget()
      ->setOption('choices', $this->getUser()->getAttribute('cars'));
  }
}

Same problem is with validatorSchema. I found that this seems to work:

<?php

class defaultActions extends sfActions
{
  public function executeIndex(sfWebRequest $request)
  {
    $this->form = new UserForm();
    $this->form['entry']['cars']
    ->getWidget()
    ->setOption('choices', $this->getUser()->getAttribute('cars'));

    // validator part
    $validatorSchema = $this->form->getValidatorSchema();
    $validatorSchema['entry']['cars']
    ->setOption('choices', array_keys($this->getUser()->getAttribute('cars')));
  }
}

I hope it'll help.