Note: Please see jeremy's answer as mine is based on his.
Thank you for your answer jeremy. Your code had a few issues, so I thought I'd post my implemented solution explaining what I did differently.
1. Override doBind()
The override of doBind() had an issue where an uncaught sfValidatorError would be thrown if the parent value didn't return clean from the validator. I wrapped it in a try/catch to suppress this.
I also altered it to work with multiple embedded forms, not just the two I specified.
protected $selectedTemplate;
public function getTemplateToEmbeddedFormKeyMap()
{
// An array of template values to embedded forms
return array(
'template1' => 'templateform1',
'template2' => 'templateform2',
'template3' => 'templateform3',
'templateN' => 'templateformN'
);
}
protected function doBind(array $values)
{
// Clean the "template" value
try
{
$this->selectedTemplate = $this->validatorSchema['template']->clean(array_key_exists('template', $values) ? $values['template'] : NULL);
}
catch(sfValidatorError $e) {}
// For each template embedded form
foreach($this->getTemplateToEmbeddedFormKeyMap() as $template => $form_key)
{
// If there is no selected template or the embedded form is not for the selected template
if ($this->selectedTemplate == NULL || $this->selectedTemplate != $template)
{
// Don't validate it
$this->validatorSchema[$form_key] = new sfValidatorPass();
}
}
// Parent
parent::doBind($values);
}
2. NEW STEP Override updateObjectEmbeddedForms()
Because I've disabled validation on some or all of my embedded forms, we now have some uncleaned data in the $values array. I don't want this data being passed to my model objects within the embedded forms, so I've overridden updateObjectEmbeddedForms()
to remove any data related to an embedded form that isn't validated.
public function updateObjectEmbeddedForms($values, $forms = null)
{
// For each template embedded form
foreach($this->getTemplateToEmbeddedFormKeyMap() as $template => $form_key)
{
// If there is no selected template or the embedded form is not for the selected template
if ($this->selectedTemplate == NULL || $this->selectedTemplate != $template)
{
// Remove the data
unset($values[$form_key]);
}
}
// Parent
parent::updateObjectEmbeddedForms($values, $forms);
}
3. Override saveEmbeddedForms()
And finally, I didn't like I had to copy and paste the entire base saveEmbeddedForms()
method and then alter it, so I refactored it to remove the embedded forms I don't want to save before passing them to the parent.
public function saveEmbeddedForms($con = null, $forms = null)
{
// Get the embedded forms
if ($forms === NULL)
{
$forms = $this->getEmbeddedForms();
}
// For each template embedded form
foreach($this->getTemplateToEmbeddedFormKeyMap() as $template => $form_key)
{
// If there is no selected template or the embedded form is not for the selected template
if ($this->selectedTemplate == NULL || $this->selectedTemplate != $template)
{
// Remove the form so it isn't saved
unset($forms[$form_key]);
}
}
// Parent
parent::saveEmbeddedForms($con, $forms);
}
Thanks again for the answer jeremy, it got me to this which works for my use case.