3
votes

I'm working on an installation of Symfony 1.4 that we've needed to re-skin to match new company branding. One of the requirements of the new skin is that radio buttons have the following syntax -

<label><input name="foo" type="radio" value="bar" id="foo_bar"><span></span></label>

However the default Symfony code for radio buttons is -

<input name="foo" type="radio" value="bar" id="foo_bar">

Where is the template that I can change to add the additional elements to surround the input tag? I've searched high and low through the code and I can't seem to find where this code is being generated.

Thanks in advance!

3

3 Answers

7
votes

You'll need to create a custom widget class. I've extended the radio widget and changed the formatter functionality.

You might need to customise this yourself a little. But the below myWidgetFormSelectRadio class will wrap each radio field in a label like you've specified.

// \lib\widget\myWidgetFormSelectRadio.class.php
class myWidgetFormSelectRadio extends sfWidgetFormSelectRadio
{
  protected function formatChoices($name, $value, $choices, $attributes)
  {
    $inputs = array();
    foreach ($choices as $key => $option)
    {
      $baseAttributes = array(
        'name'  => substr($name, 0, -2),
        'type'  => 'radio',
        'value' => self::escapeOnce($key),
        'id'    => $id = $this->generateId($name, self::escapeOnce($key)),
      );

      if (strval($key) == strval($value === false ? 0 : $value))
      {
        $baseAttributes['checked'] = 'checked';
      }

      $inputs[] = array(
        'input' => $this->renderContentTag('label', $this->renderTag('input', array_merge($baseAttributes, $attributes)), array('for' => $id)),
      );
    }

    return call_user_func($this->getOption('formatter'), $this, $inputs);
  }

  public function formatter($widget, $inputs)
  {
    $rows = array();
    foreach ($inputs as $input)
    {
      $rows[] = $input['input'].$this->getOption('label_separator');
    }

    return implode($this->getOption('separator'), $rows);
  }
}

Then in your form classes

// \lib\form\myForm.class.php
public function configure()
{
    $this->widgetSchema['my_field'] = new myWidgetFormSelectRadio(array('choices' => $choices));

    // ....
}

Are you using Twitter Bootstrap by chance? If so, then you'll want to extend the Symfony checkbox widget as well. If you do this then you might want to extend the sfWidgetFormChoice class and change the getRenderer() method so that it uses your myWidgetFormSelectRadio and myWidgetFormSelectCheckbox class when rendering radio/checkbox fields.

// \lib\widget\myWidgetFormChoice.php
class myWidgetFormChoice extends sfWidgetFormChoice
{
  public function getRenderer()
  {
    if ($this->getOption('renderer'))
    {
      return $this->getOption('renderer');
    }

    $prefix = $this->getOption('use_my_custom_widget') ? 'my' : 'sf';

    if (!$class = $this->getOption('renderer_class'))
    {
      $type = !$this->getOption('expanded') ? '' : ($this->getOption('multiple') ? 'checkbox' : 'radio');
      $class = sprintf($prefix . 'WidgetFormSelect%s', ucfirst($type));
    }

    return new $class(array_merge(array('choices' => new sfCallable(array($this, 'getChoices'))), $this->options['renderer_options']), $this->getAttributes());
  }
}

Then in your form class

public function configure()
{
    $this->widgetSchema['my_field'] = new myWidgetFormChoice(array(
         'choices' => $choices,
         'expanded' => true,
         'use_my_custom_widget' => true,
    ));

    // ....
}
1
votes

Are you generating the forms in backend with admin generator?

if so you should look for the forms in the cache folder located on .../cache/app/enviroment/modules/

you will note that there will be folders with "auto" prefix, those folders are auto generated by symfony to cache the modules, if you used the application within the development enviroment "app_dev".

Then look for the module where you need to change the views on .../cache/backend/dev/modules/autoModule/templates/

you can find in this link a little description of each file located under Templates Customization.

You need to copy the files you need on .../apps/backend/module/templates/ folder you can create the templates folder. Note that if you change the config.yml of the module the changes will be applied in cache, so you have to update the template again (copy and paste from template located on cache to your modulee/templates)

Now the hard way, I found that I can modify the forms HTML in a more fast and easy way with javascript, thats what I did with some symfony projects before, hope it helps.

0
votes

Puh, Symfony 1. Long ago since I worked with. I gravedigged the old symfony documentation, and a custom widget could be, what you want. I don't think, symfony 1 has form theming like symfony 2.