简体   繁体   中英

How to set the choices of a Symfony EntityType form field after the form has been created and handled?

I am working with Symfony 3.4 and would like to create a simple form which presents a list entities which can be selected for deletion using checkboxes:

  • The controller which creates and handles the form loads a list of entities from the DB which are then added to the form.
  • The controller uses some additional parameters to offer paging, eg if there are 10.000 entities in the DB the user can choose to load only the first 50.

The problem is, that "the first 50 entities" depends on wether entities have been delete / the form has been handled.

  • To handle the form in the controller I have to create it first
  • To create the form I need to load a list of entities from the DB to set them as choises
  • This list will contain the first 50 entities
  • If the user has chosen to delete the first 10 entities this is done when handling the form.

class SomeController
{
    public function deleteUsersAction(Request $request)
    {
        $users = $this->loadUsersFromDB(50);

        $form = $this->creatFormBuilder()
            ->add('users', EntityType::class, [
                'class' => 'AppBundle:User',
                'choices' => $users,                  // $users are added here
                'multiple' => true,
                'expanded' => true,
            ])
            ->getForm();

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $users = $form->getData();
            $this->deleteUsers($user);

            // Load the now first 50 users
            $users = $this->loadUsersFromDB(50);

            // How to add these users to the form??
        }

        return $this->render('AppBundle::user_list.html.twig', ['form' => $form->createView()]);
    }
}

How to set the correct users to the form after the submitted users have been deleted?


Edit

To answer a question from the comments I provide a small example:

  • Let's say the form shows the first 5 users.
  • When the page is called the first time the form is not submitted. The controller loads the following first users, uses them to create the form and to display the page:
  • Bob
  • Alice
  • Mike
  • John
  • Bill
  • On the page the user selects Bob and Alice for deletion and submits the form.
  • The controller is called again, and the list of the first 5 users is loaded to create the form. This list is exactly the same as before.
  • However, as the form was now submitted the data is handled and Bob and Alice are deleted.
  • Now we cannot return the created form because it still contains the entries for Bob and Alice...
  • We have to run $users = $this->loadUsersFromDB(5) again to get the correct result, like
  • Mike
  • John
  • Bill
  • Jim
  • Tom

The Problem:

  • The list of users has to be loaded before the form is created, because we need this list to create the form.
  • The form has to be created so that we can handle it
  • Handling the form does change the list of users
  • Thus after handling the form we need to load the list of users again.

So: Loading the list of users before to form is handled is necessary work, because the list changes when the form is handled.

How can this work be avoided?

Of course loading 5 users as in the example is no big deal, but in real code this might be hundreds of heavy entities and running the same code twice might have a significant performance impact.

I think you did not understood my proposal in the comment, so I'll explain here in more detail /also now I write from the laptop:)/

class SomeController {
    public function deleteUsersAction(Request request) {
        $users = $this->loadUsersFromDB(50);        

        $form = $this->creatFormBuilder()
            ->add('users', EntityType::class, [
                'class' => 'AppBundle:User',
                'choices' => $users,                  // $users are added here
                'multiple' => true,
                'expanded' => true,
            ])
            ->getForm();

         $form->handleRequest($request);
         if ($form->isSubmitted() && $form->isValid()) {
             $users = $form->getData();
             $this->deleteUsers($user);

             // Load the now first 50 users
             $users = $this->loadUsersFromDB(50); <-- you don't need this

             // Q: How to add these users to the form??
             // A: When you return a redirect response to the same page /you can also pass any query parameters if you had any filters and etc../
             //    This will ensure that the page is loaded properly with the new list of the users and Bob and Alice will NOT be in the list
             //    If you don't do it with a redirect and the user submits the form the browser remembers the data and if the users hits the refresh button of the browser it will resubmit the form and with your approach it may delete next 2 users /Mike and John/.
             return $this->redirectToRoute('YOUR_ROUTE', $request->query->all());
         }

         return $this->render('AppBundle::user_list.html.twig', ['form' => $form->createView()]);
    }
}```

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM