2009-01-19

symfony & mark fields as required



By default required fields in symfony form framework are not marked with '*'

How could we do this ?
- you could manually create form with fields (a lot of code, a lot of efforts)
- create own form formatter and using it with form class. It will automatically mark fields as we need ! (that's nice news :)

so - let's go !
1. Create own formatter (sfWidgetFormSchemaFormatter%)

class sfWidgetFormSchemaFormatterStore extends sfWidgetFormSchemaFormatter
{
protected
$rowFormat = "\n %label%\n %error%%field%%help%%hidden_fields%\n\n",
$errorRowFormat = "\n%errors%\n",
$helpFormat = '
%help%',
$decoratorFormat = "\n %content%
",
$requiredTemplate= ' *',
$validatorSchema = null;

/**
* Generates the label name for the given field name.
*
* @param string $name The field name
* @return string The label name
*/
public function generateLabelName($name)
{
$label = parent::generateLabelName($name);

$fields = $this->validatorSchema->getFields();
if($fields[$name] != null) {
$field = $fields[$name];
if($field->hasOption('required') && $field->getOption('required')) {
$label .= $this->requiredTemplate;
}
}
return $label;
}

public function setValidatorSchema(sfValidatorSchema $validatorSchema)
{
$this->validatorSchema = $validatorSchema;
}
}


we have some useful changes:
- add css classes
- add $requiredTemplate with required field template
- add injection of validatorSchema

2. Owerride __toString method (form class) - for using own formatter

class StoreRegistrationForm extends BaseStoreDetailsForm
{
public function configure()
{
// ...
}

public function render($attributes = array())
{
$formatterObj = $this->widgetSchema->getFormFormatter();
if(!is_null($formatterObj)) { $formatterObj->setValidatorSchema($this->getValidatorSchema()); $this->widgetSchema->getFormFormatter()->setTranslationCatalogue("register_store_form");
}
return parent::render($attributes);
}

public function __toString()
{
try
{
return $this->renderUsing('Store');
}
catch (Exception $e)
{
self::setToStringException($e);
// we return a simple Exception message in case the form framework is used out of symfony.
return 'Exception: '.$e->getMessage();
}
}
}


3. as you see - TranslationCatalogue has been injected not in configure method.
If you use other than messages.xml - you should call setTranslationCatalogue in render block

public function render($attributes = array())
{
$formatterObj = $this->widgetSchema->getFormFormatter();

if(!is_null($formatterObj)) {
$formatterObj->setValidatorSchema($this->getValidatorSchema());
$this->widgetSchema->getFormFormatter()->setTranslationCatalogue("register_store_form");
}

return parent::render($attributes);
}


that's all )

2 comments:

matt said...

this does not work for forms with embedded forms, i.e. embedForm as the formatter is not passed into these

henrikbjorn said...

@matt easy just make a form all your forms extends like the BaseFormDoctrine :)