M
M
Max2019-10-09 02:50:26
symfony
Max, 2019-10-09 02:50:26

How in symfony 3.4 to display and submit a form for an entity in the list of entities?

Hello, I have not been learning symfony for so long and am stuck on the following point.

  • created an entity with fields for the database, a controller and a form;
  • in the controller, in the method that displays the list of instances of this entity, I create a form for each entity in the instance loop;
  • I assign the created form to the property of each instance;
  • I pass an array of entities to the template, where a list with data and a form for editing each instance is displayed in a loop.

I also set conditions in the controller that are triggered when the form is submitted and save the changes:
if($form->isSubmitted() && $form->isValid()){...}
But when the form is submitted, the changes are always saved only for the very first instance, even if I changed the data from another instance. If, after sending, the redirect is not returned in the controller ( return $this->redirectToRoute(...); ), then the data changed in any form is applied to all instances.
Questions:
What is my mistake?
How to correctly display a list of entities with editing forms for each?
Thank you!
Entity code:
// src/AppBundle/Entity/Account.php

namespace AppBundle\Entity;

class Account
{
//...
    /**
     * @var FormInterface
     */
    private $form;
    /**
     * @var FormView
     */
    private $formView;
//...
}

Controller method code:
// src/AppBundle/Controller/AccountController.php

//...
/**
     * @Route("/accounts/", name="account_list")
     * @Template()
     */
    public function indexAction(Request $request)
    {
        $accounts = $this
            ->getDoctrine()
            ->getRepository('AppBundle:Account')
            ->findActive();

        foreach ($accounts as $key => $account){

            $form = $this->createForm(AccountType::class, $account);

            $form->add('submit', SubmitType::class);

            $formView = $form->createView();

            $form->handleRequest($request);

            $account->setForm($form);

            $account->setFormView($formView);

            if($form->isSubmitted() && $form->isValid()){

                $data = $form->getData();

                $this->addFlash('success', 'Saved');

                $em = $this->getDoctrine()->getManager();
                $em->persist($data);
                $em->flush();

                return $this->redirectToRoute('account_list');
            }
        }

        return [
            'accounts' => $accounts,
        ];
    }
//...

Template code:
// src/AppBundle/Resources/views/account/index.html.twig
//...
{% block body %}
    <ul class="list-group">
        {% for account in accounts %}

            <li class="list-group-item flex-column align-items-start">
                <div class="d-flex w-100 justify-content-between">
                    <h5 class="mb-1">{{ account.login }}</h5>
                    <small>{{ account.id }}</small>
                </div>

                {{ form_row(account.formView) }}

            </li>

        {% endfor %}
    </ul>
{% endblock %}
//...

Answer the question

In order to leave comments, you need to log in

3 answer(s)
B
BoShurik, 2019-10-09
@maximrabotaet

$form = $this->container->get('form.factory')
    ->createNamed(
        'account_'. $account->getId(), 
        AccountType::class, 
        $account
    )
;

About the code
public function indexAction(Request $request)
{
    $accounts = $this
        ->getDoctrine()
        ->getRepository('AppBundle:Account')
        ->findActive();

    $forms = [];
    foreach ($accounts as $key => $account){

        $form = $this->container->get('form.factory')->createNamed('account_'. $account->getId(), AccountType::class, $account);

        // Не надо добавлять кнопки сабмита, их рекомендуется добавлять непосредственно в шаблоне обычным html
        // $form->add('submit', SubmitType::class);

        $form->handleRequest($request);

        // Не надо инжектить форму в сущность, легче просто передать формы в шаблон
        // $account->setForm($form);
        // $account->setFormView($formView);

        if($form->isSubmitted() && $form->isValid()){

            // Объекты передаются по ссылке, нет смысла в получение $account повторно
            // $data = $form->getData();

            $this->addFlash('success', 'Saved');

            $em = $this->getDoctrine()->getManager();
            // Это актуально только для создания сущности, при редактировании - это не нужно
            // $em->persist($data);
            $em->flush();

            return $this->redirectToRoute('account_list');
        } else {
            $forms[$account->getId()] = $form->createView();
        }
    }

    return [
        'forms' => $forms,
        'accounts' => $accounts,
    ];
}

{# {{ form_row(account.formView) }} #}
{{ form_start(forms[account.id]) }}
    {{ form_widget(forms[account.id]) }}
    <button>Submit</button>
{{ form_end(forms[account.id]) }}

PS Ideally, the update and the list of entities should be divided into different actions

K
kafkiansky, 2019-10-09
@mad_maximus

Horrible. Have you come up with anything worse? Regarding the question: look at the layout and at the names of the forms that you got. If anything, all the forms you've rendered have the same name, so only one of them is submitted. To make it clear which form is being processed, if there are many such forms on the page, the FormType method getBlockPrefix () is overloaded, where a string with the name of the form is simply returned. This is the first. Second. Entity fields are not equal to form fields. You don't need to use an entity to map to a form. And adding the FormInterface field to the entity is like in general? You simply output data about entities in a loop, for each of which you make a block with actions. For any action, send the id of this entity. Thus, the form is one, and any entity can be edited.

D
Denis, 2019-10-09
@prototype_denis


Hello, not so long learning symfony
I will not disrupt the learning process with a ready-made solution, but just a hint.
Google the symfony dock for form collections (CollectionType) and form themes (form_theme).

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question