One form for multiple addresses in Symfony - Twig One form for multiple addresses in Symfony - Twig symfony symfony

One form for multiple addresses in Symfony - Twig


revised answer with regards to what we talked about in chat:

As I wrote in the comment, I'm sure you only need to setup a collection field. The whole complexity then basically goes away.

A very simple example would be:

controller:

public function editCompanyAction(Request $request){    // get the data anyway you see fit and produce a model (this could also be a dedicated DTO)    $company = $this->getInput();    // create the form    $form = $this        ->createForm(CompanyWithAddressesType::class, $company)        ->handleRequest($request)    ;    // handle submission    if ($form->isSubmitted() && $form->isValid()) {        dump($form->getData()); // === $company    }    return $this->render('default/index.html.twig', [        'form' => $form->createView(),    ]);}

the forms

The important part here is that the names of the fields you add match the keys in the array which is supplied as data!

class CompanyWithAddressesType extends AbstractType{    /**     * {@inheritdoc}     */    public function buildForm(FormBuilderInterface $builder, array $options)    {        // combine the company with a collection of addresses:        $builder            ->add('gegevens', CompanyType::class)            ->add('addresses', CollectionType::class, [                'entry_type' => AddressType::class,            ])        ;    }}class CompanyType extends AbstractType{    /**     * {@inheritdoc}     */    public function buildForm(FormBuilderInterface $builder, array $options)    {        // all the fields that are *extra* for companies, address fields are inherited        // because this type extends the address type (see below getParent)        $builder            ->add('NawWebsite', TextType::class)            ->add('email1', TextType::class)            ->add('AdrNaam1', TextType::class)        ;    }    /**     * @return @inheritdoc     */    public function getParent()    {        return AddressType::class;    }}class AddressType extends AbstractType{    /**     * {@inheritdoc}     */    public function buildForm(FormBuilderInterface $builder, array $options)    {        // all the fields that define an address        $builder            ->add('AdrStraat', TextType::class)            ->add('AdrHuisnummer', TextType::class)            ->add('AdrPostcode', TextType::class)            ->add('NawFactuurAdres', CheckboxType::class)        ;    }}

twig:

Simply output the form. Any form customization is applicable

{{ form_start(form) }}    <div>        <h4>Company</h4>        {{ form_row(form.gegevens.NawWebsite) }}        {{ form_row(form.gegevens.email1) }}        {{ form_row(form.gegevens.AdrNaam1) }}    </div>    <div>        <h4>Main address</h4>        {{ form_rest(form.gegevens) }}    </div>    <div>        <h4>Extra addresses</h4>        {% for address in form.addresses %}            {{ form_errors(address) }}            {{ form_widget(address) }}        {% endfor %}    </div>    <button>Submit</button>{{ form_end(form) }}


I think you would need to place the form outside of the loop and then have a hidden input field that identifies the address which needs to be saved on submit. So when the other fields are not displayed, they are not submitted.That means you need some Javascript logic to display and hide the addresses.

Twig template (editing form):

{{ form_start(form_company_adres, {'  method': 'POST'}) }}{% for address in client.addresses %}    <div id="address-{{ loop.index }}" class="address">        <input type="hidden" name="address-number" value="{{ loop.index }}"/>        {{ form_row(form_company_adres._token) }}            <section class="collapse" id="adres_plus">                <div id="adres" class="new-adres collapse right-cont-grey">                    <div class="col-sm-12">                        [...] // Form_widgets with values from database                </div>            </section>    </div>{% endfor %}{{ form_end(form_company_adres) }}