Skip to content

Instantly share code, notes, and snippets.

@spcmky
Last active April 10, 2019 07:52
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save spcmky/8512371 to your computer and use it in GitHub Desktop.
Save spcmky/8512371 to your computer and use it in GitHub Desktop.
Symfony2 Form Type Fieldset Example
# app/config/config.yml
twig:
form:
resources:
- 'AcmeDemoBundle:Form:fields.html.twig'
<?php
// src/Acme/DemoBundle/Form/ExampleType.php
namespace Acme\DemoBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Acme\DemoBundle\Form\Type\FieldsetType;
class ExampleType extends AbstractType {
protected $options;
public function __construct ( $options = array() ) {
$this->options = $options;
}
public function buildForm ( FormBuilderInterface $builder, array $options ) {
$builder
->add('firstname')
->add('lastname')
->add('email','email');
$builder->add('credentials',new FieldsetType(),array(
'label' => false,
'required' => false,
'mapped' => false,
'title' => 'Credentials',
'subforms' => array(
array(
'name'=>'username',
'type'=>'text',
'attr'=> array(
'required' => true
)
),
array(
'name'=>'password',
'type'=>'password',
'attr'=> array(
'required' => true
)
)
)
)
);
}
public function getName() {
return 'acme_mainbundle_exampletype';
}
}
{# src/Acme/DemoBundle/Resources/views/Form/fields.html.twig #}
{% block fieldset_widget %}
{% spaceless %}
<fieldset {{ block('widget_container_attributes') }}>
{% if title is defined %}<legend>{{ title }}</legend>{% endif %}
{{ form_widget(form) }}
</fieldset>
{% endspaceless %}
{% endblock %}
<?php
// src/Acme/DemoBundle/Form/Type/FieldsetType.php
namespace Acme\DemoBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class FieldsetType extends AbstractType {
public function setDefaultOptions ( OptionsResolverInterface $resolver ) {
$resolver->setDefaults(array(
'title' => false,
'subforms' => array(),
'options' => array()
));
}
public function buildForm ( FormBuilderInterface $builder, array $options ) {
if ( !empty($options['subforms']) ) {
foreach ( $options['subforms'] as $f ) {
$builder->add($f['name'],$f['type'],$f['attr']);
}
}
}
public function buildView ( FormView $view, FormInterface $form, array $options ) {
if ( isset($options['title']) || $options['title'] !== false ) {
$view->vars['title'] = $options['title'];
}
}
public function getName() {
return 'fieldset';
}
}
@mchubby
Copy link

mchubby commented May 27, 2014

Hello, and thanks for this interesting piece of code.
However I have some doubts regarding the use of the field's mapped attribute set to false:

Here is my sample Silex app:

<?php
$loader = require 'vendor/autoload.php';
$loader->add("Acme",__DIR__);

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Silex\Provider\FormServiceProvider;
use Silex\Provider\TwigServiceProvider;
use Silex\Provider\TranslationServiceProvider;

use Acme\ExampleType;

$app = new \Silex\Application();
$app['debug'] = true;
$app->register(new TranslationServiceProvider());
$app->register(new FormServiceProvider());
$app->register(new TwigServiceProvider(), array(
    'twig.path' => __DIR__ . '/Acme',
    'twig.templates' => array(
        'form.twig' => "{% form_theme form 'fields.twig' %}
<h4>Userform</h4>
{{ form(form) }}
",
        'fields.twig' => "{% block fieldset_widget %}
    {% spaceless %}
        <fieldset {{ block('widget_container_attributes') }}>
            {% if title is defined %}<legend>{{ title }}</legend>{% endif %}
            {{ form_widget(form) }}
        </fieldset>
    {% endspaceless %}
{% endblock %}"
    ),
));


$app->get('/', function () use ($app) {
    $form = $app['form.factory']->create(new ExampleType());
    return $app['twig']->render('form.twig', array(
        'form' => $form->createView()
    ));
});

$app->post('/', function (Request $request) use ($app) {
    $form = $app['form.factory']->create(new ExampleType());
    $form->handleRequest($request);
    if (!$form->isSubmitted()) {
        return new Response("NOT SUBMITTED", 500);
    }
    return print_r($form->getData(), true);
});


$app->run();
?>

When it's false:

Array
(
    [firstname] => Foo
    [lastname] => Bar
    [email] => Zab@example.com
)

When mapped is the default value (true) I get:

Array
(
    [firstname] => Foo
    [lastname] => Bar
    [email] => Zab@example.com
    [credentials] => Array
        (
            [username] => Oof
            [password] => 
        )

)

It's kind of a pain too, having to refer to the fieldset values as $data['credentials']['username'] ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment