Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

edit Symfony2 big entity in form with tabs

I'm building form using Sf2's form builder.

public function buildForm(FormBuilder $builder, array $options)
{
    $builder->add('firstName')
            ->add('lastName')...

The Entity has a lot of fields and I'd like to put them in jQuery UI Tabs. But in twig template I'd like to use single command

<form action="#" method="post" {{ form_enctype(form) }}>
    {{ form_widget(form) }}
    <input type="submit" value="Save"/>
</form>

What is best solution?

edit **

To be more conrete: I have 4 fields: firstName, lastName, birthDate, deathDate. I want first 2 fields to be on first tab and the last 2 fields to be on second tab. I want to keep way of rendering the form as mentioned earlier.

I though of a solution to create my own fields not conneceted to underlaying object which will render required html tags (h3, div, etc).

like image 662
koral Avatar asked Oct 08 '22 20:10

koral


2 Answers

I defined my own field called 'Tab' and add it when new tab should appear.

<?php
//\src\Alden\xyzBundle\Form\Type\TabsType.php

namespace Alden\BonBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\CallbackValidator;
use Symfony\Component\Form\FormValidatorInterface;
use Symfony\Component\Form\Form;

class TabsType extends AbstractType {

    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->setAttribute('starting', $options['starting']);
        $builder->setAttribute('ending', $options['ending']);
        $builder->setAttribute('header', $options['header']);
    }

    public function buildView(FormView $view, FormInterface $form)
    {
        $parent = $form->getParent();
        if (is_null($parent->getParent()))
        {
            $tabs = $this->findTabs($parent);
        }
        else
        {
            $tabs = array();
        }
        $view->set('starting', $form->getAttribute('starting'));
        $view->set('ending', $form->getAttribute('ending'));
        $view->set('header', $form->getAttribute('header'));
        $view->set('tabs', $tabs);
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'property_path' => false,
            'starting' => true,
            'ending' => true,
            'header' => false,
        );
    }

    public function getName()
    {
        return 'tabs';
    }

    public function getParent(array $options)
    {
        return 'field';
    }

    private function findTabs(Form $form)
    {
        $prefix = $form->getName();
        $tabs = array();
        foreach ($form->getChildren() as $child)
        {
            foreach ($child->getTypes() as $type)
            /* @var $child \Symfony\Component\Form\Form */
            {
                if (get_class($type) == __NAMESPACE__ . '\TabsType')
                {
                    if ($child->getAttribute('starting'))
                    {
                        $tabs[$prefix . '_' . $child->getName()] = $child->getAttribute('label');
                    }
                }
            }
        }
        return $tabs;
    }

}

?>

and Twig

{# \src\Alden\xyzBundle\Resources\views\Form\fields.html.twig #}
{% block tabs_row %}
{% if header %}
<ul>
    {% for tid, t in tabs %}
        <li>
            <a href="#{{ tid }}">{{ t }}</a>
        </li>
    {% endfor %}
</ul>
{% endif %}
{% if ending %}
</div>
{% endif %}
{% if starting %}
<div id="{{ id }}">
{% endif %}
{% endblock %}

and usage in form builder:

public function buildForm(FormBuilder $builder, array $options)
{
    $builder
            ->add('tabs_head', new TabsType(), array(
                'ending' => false,
                'starting' => false,
                'header' => true
            ))
            ->add('tab_1', new TabsType(), array(
                'ending' => false,
                'label' => 'Podstawowe'
            ))
            ->add('firstName', null, array(
                'label' => 'Imię'
            ))
            ->add('lastName', null, array(
                'label' => 'Nazwisko'
            ))
            ->add('tab_contact', new TabsType(), array(
                'label' => 'Kontakt'
            ))
            ->add('address', new AddressType(), array(
                'label' => 'Adres zameldowania'
            ))
            ->add('tabs_end', new TabsType(), array(
                'starting' => false
            ))
    ;
}
like image 93
koral Avatar answered Oct 11 '22 00:10

koral


If you want a form to act like a form wizard you could look at look at the multi-step form bundle

It's pretty nice, you can for example, define step one as filling in software details and then on step2, fill out version details. or whatever you want.

Features

  • navigation (next, back, start over)
  • step descriptions
  • skipping of specified steps
  • different validation group for each step
  • dynamic step navigation

And here is a live demo

like image 30
Flukey Avatar answered Oct 11 '22 00:10

Flukey