vellmur
vellmur

Reputation: 272

Update single entity in form collection

I have a page where i can add/update some entities from database. For update i have a table where i can have a list of each row from some table. I need to have possibility to edit this row(entity) and save/delete. So that means that each row of table must have form fields for one object from database. And i wanted to have possibility to validate this forms. So i have many forms with same type in one page.
Previous i just created a loop where i saved in array of forms with same formtype this way:

    $formsArray = [];

    foreach ($gardens as $garden) {
        array_push($formsArray, $this->createForm('AppBundle\Form\GardenType', $garden)->createView());
    }   

Then i showed it in template(twig):

 {%  for key, form in forms %}
      <tr {% if key is not divisible by (2) %} class="gray" {% endif %}>
          {{ form_start(form, { 'attr': {'name' : 'garden ', 'action': path('ajax_garden_update', {id : form.vars.value.id}), 'role' : 'form', 'class' : 'ajaxUpdate'} }) }}
              <td class="form-group">{{ form_widget(form.name) }}</td>
              <td class="form-group">{{ form_widget(form.rows) }}</td>
              <td class="form-group">
              <span id="form-status"><button type="submit" class="btn btn-default btn-icon btn-save"><i class="icon-disk"></i></button></span>
          </td>
          {{ form_end(form) }}
      </tr>
 {% endfor %}  

In each row of table i have submit button, so i can serialize form, send it to server, and that how i updated entity:

public function ajaxUpdateAction(Request $request, Garden $garden)
{
    if ($request->isXMLHttpRequest()) {
        $form = $this->createForm(GardenType::class, $garden);
        $form->handleRequest($request);

        if ($form->isValid()) {
            $gardenManager = $this->get('app.manager.garden');
            $gardenManager->updateGarden($garden);

            return new JsonResponse(['code' => 202, 'status' => 'success'], 202);
        } else {
            $serializer = $this->get('jms_serializer');
            return new JsonResponse($serializer->serialize(['error' => $form], 'json'), 500);
        }
    }
    return new Response('Request not valid', 400);
}  

But i have a feeling that create an array for forms in loop it is a bad idea for memory and speed. So i tried to use a form collection. But problem that i dont understand how to validate and update single entity from collection. I getting errors, when i try to handle request and validate collection. First of all, i got error that form havent csrf token (form can have only one token so i sending forms without token, maybe i need to find a way to generate token for each row). Then i disabled csrf protection and got error that form cannot have extra fields. Maybe i do something wrong? This is my collection.

<?php

namespace AppBundle\Form\Collection;

use AppBundle\Entity\Garden;
use AppBundle\Form\GardenType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class GardensType extends AbstractType
{
/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('garden', CollectionType::class, [
        'entry_type' => GardenType::class,
        'allow_add'    => true,
        'prototype' => true,
        'csrf_protection' => false
    ]);
}

/**
 * @param OptionsResolver $resolver
 */
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'csrf_protection' => false,
        'validation_groups' => false,
        'allow_extra_fields' => true
    ));
}

}

And my code in controller:

/**
 * @param Request $request
 * @param Garden $garden
 * @return JsonResponse|Response
 */
public function ajaxUpdateAction(Request $request, Garden $garden)
{
    if ($request->isXMLHttpRequest()) {

        $form = $this->createForm(GardensType::class);

        $form->handleRequest($request);

        if ($form->isValid()) {

            $gardenManager = $this->get('app.manager.garden');
            $gardenManager->updateGarden($garden);

            return new JsonResponse(['code' => 202, 'status' => 'success'], 202);
        } else {
            $serializer = $this->get('jms_serializer');

            return new JsonResponse($serializer->serialize(['error' => $form], 'json'), 500);
        }
    }

    return new Response('Request not valid', 400);
    }

P.S. I attached image for better understanding. Each row it is form from collection and each button in row use js code that finds closest form and serialize fields in this form, then data goes to controller.

enter image description here

Upvotes: 1

Views: 1524

Answers (0)

Related Questions