ShellCode
ShellCode

Reputation: 1172

Handle form on different route from where it's built Symfony 3

I'm actually creating a website (with symfony 3) where the login form is on the main page (route /). And I would like to handle this form on the /login route.

Unfortunately I don't know how to do that because my form is built in the indexAction() and my loginAction() has no visibility on the $form built in index...

/**
 * @Route("/", name="home")
 */
public function indexAction()
{
    $user = new User();

    $form = $this->createFormBuilder($user)
        ->setAction($this->generateUrl('login'))
        ->setMethod('POST') //btw is this useless ?? Is it POST by default ?
        ->add('Login',   TextType::class)
        ->add('Password',    TextType::class)
        ->add('save', SubmitType::class, array('label' => 'Sign In'))
        ->getForm();

    return $this->render('ShellCodeHomeBundle:Home:index.html.twig', array (
        'login' => '',
        'form_signin' => $form->createView(),
    ));
}

/**
 * @Route("/login", name="login")
 */
public function loginAction(Request $request)
{
    $user = new User();

    //how do I handle the form ????
    $form->handleRequest($request);

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

        $em = $this->getDoctrine()->getManager();
        $user = $form->getData();
        //...
    }

    return $this->render('ShellCodeHomeBundle:Home:index.html.twig', array (
        'login' => $user->getLogin(),
    ));
}

I guess it's useless to tell that, but I'm using twig and I insert the form like this :

<div class="col-lg-12" style="text-align: center;">
    {{ form_start(form_signin) }}
    {{ form_widget(form_signin) }}
    {{ form_end(form_signin) }}
</div>

Hope you will able to help me ! Thanks !

Upvotes: 0

Views: 1343

Answers (4)

Mohammed Abdelouahab
Mohammed Abdelouahab

Reputation: 89

i know what you means, easy example.

Main route

$addCandidate = new Candidate();
        $addCandidateForm = $this->createForm(AddCandidateForm::class, $addCandidate, [
            'action' => '/candidate',
            'method' => 'POST',
            'attr' => [
                'id' => 'add_candidate_form',
            ]
        ]);
        $addCandidateForm->handleRequest($request);
        return $this->render('candidate/candidates_list.html.twig', [
            'addCandidateForm' => $addCandidateForm
        ]);

Seconde route

$candidate = new Candidate();
            $form = $this->createForm(AddCandidateForm::class, $candidate);
            $form->handleRequest($request);

you can get $form and do what you want like you are in first route.

Upvotes: 0

Claod
Claod

Reputation: 21

Here is the answer :

In your other function just build the same form, handle the request and check if it's valid in this second method.

#[Route('/url', name: 'app_url')]
public function index(Request $request, EntityManagerInterface $em) : Response {
    $entity = new Entity();
    $data = 'some data';

    $form = $this->createForm(EntityFormType::class, $entity, [ 'data' => $data, 'action' => 'other_url' ]);
    /** extra code and send the request **/
}

then in the second controller function :

#[Route('/otherUrl', name: 'other_url')]
public function validation(Request $request, EntityManagerInterface $em) : Response {
    /** SAME FORM CODE HERE **/
    $entity = new Entity();
    $form = $this->createForm(EntityFormType::class, $entity, [ 'data' => $data, 'action' => 'other_url' ]);
    /** extra code and send the request **/
}

The form will be received and the framework will understand it correctly, it's like it's the same form, each form data will be put in the right place in the new form instance faking it's the same.

Upvotes: 0

KhorneHoly
KhorneHoly

Reputation: 4766

Do not build your form within the controller, that's a bad practice, because you can't reuse this code.

You should create your form within FormType and define them as a service. That way, you'll be able to reuse this form as often as you need it to.

Taken from the docs linked below, here's an example for the FormType:

namespace AppBundle\Form;

use AppBundle\Entity\Post;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;

class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('summary', TextareaType::class)
            ->add('content', TextareaType::class)
            ->add('authorEmail', EmailType::class)
            ->add('publishedAt', DateTimeType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Post::class,
        ));
    }
}

Then you could use the FormType as in this example:

use AppBundle\Form\PostType;

// ...
public function newAction(Request $request)
{
    $post = new Post();
    $form = $this->createForm(PostType::class, $post);

    // ...
}

For detailed information, check the docs

Upvotes: 3

Fyntasia
Fyntasia

Reputation: 1143

Create a custom form type.

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\{
    PasswordType, SubmitType, TextType
};
use Symfony\Component\Form\FormBuilderInterface;

class LoginForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('Login', TextType::class)
            ->add('Password', PasswordType::class)
            ->add('save', SubmitType::class, [
                'label' => 'Sign In'
            ])
        ;
     }
 }

Upvotes: 2

Related Questions