craue / CraueFormFlowBundle

Multi-step forms for your Symfony project.
MIT License
736 stars 118 forks source link

Validation skipped using multistep flow on the same form #361

Closed migmax48 closed 4 years ago

migmax48 commented 4 years ago

Hi, I've developed on Symfony 4.x a multistep flow on the same form entity. Both Assert and Constraint not working.

Flow:

class SignupFlow extends FormFlow {
    protected $allowDynamicStepNavigation = true;

    protected function loadStepsConfig() {
        return [
            [
                'label' => 'Dati Account',
                'form_type' => SignupFormType::class,
            ],
            [
                'label' => 'Tipologia Account',
                'form_type' => SignupFormType::class
            ],
            [
                'label' => 'Dati Contatto',
                'form_type' => SignupFormType::class
            ],
            [
                'label' => 'Altre Informazioni',
                'form_type' => SignupFormType::class
            ],
            [
                'label' => 'Conferma Dati',
                'form_type' => SignupFormType::class
            ],
        ];
    }
}

My Form:

class SignupFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        switch ($options['flow_step']) {
            case 1:
                $builder->add('email',RepeatedType::class,[
                    'type' => EmailType::class,
                    'invalid_message' => 'L\'indirizzo email non coincide',
                    'first_options'  => [
                        'label' => 'Indirizzo Email',
                        'attr' => ['placeholder' => 'Inserisci il tuo indirizzo email','class' => 'form-control-sm','maxlength' => 255]
                    ],    
                    'second_options'  => [
                        'label' => 'Ripeti Email',
                        'attr' => ['placeholder' => 'Ripeti il tuo indirizzo email','class' => 'form-control-sm','maxlength' => 255]
                     ],
                    'required' => false,
                ])
                ->add('password',RepeatedType::class,[
                    'type' => PasswordType::class,
                    'invalid_message' => 'La password non coincide',
                    'first_options'  => ['label' => 'Password','attr' => ['placeholder' => 'Inserisci la password','class' => 'form-control-sm','maxlength' => 255]],
                    'second_options' => ['label' => 'Ripeti Password','attr' => ['placeholder' => 'Riscrivi la password','class' => 'form-control-sm','maxlength' => 255]]
                ])
                ->add('nazione',CountryType::class,[
                    'label' => 'Nazione',
                    'attr' => ['placeholder' => 'Seleziona la nazione','class' => 'form-control-sm','maxlength' => 255],
                    'data' => 'IT'
                ])
                ->add('telefono',TelType::class,[
                    'label' => 'Telefono',
                    'attr' => ['placeholder' => 'Inserisci il tuo recapito telefonico','class' => 'form-control-sm','maxlength' => 20],
                    'required' => false,
                    'empty_data' => '',
                    'constraints' => [
                        new Length(['min' => 3]),
                    ],
                ]);
        break;
...
...

My action:

    public function signup(Request $request,Session $session,UserPasswordEncoderInterface $passwordEncoder,ValidatorInterface $validator)
    {

        $formData = new Account(); // Your form data class. Has to be an object, won't work properly with an array.

        $flow = $this->get('buyondrop.signup'); // must match the flow's service id
        $flow->bind($formData);

        // form of the current step
        $form = $flow->createForm();

        if ($flow->isValid($form)) {
            $flow->saveCurrentStepData($form);

            if ($flow->nextStep()) {
                // form for the next step
                $form = $flow->createForm();

            } else {
                // flow finished
                $em = $this->getDoctrine()->getManager();
                $em->persist($formData);
                $em->flush();

                $flow->reset(); // remove step data from the session

                return $this->redirect($this->generateUrl('home')); // redirect when done
            }
        }

        return $this->render('home/signup.html.twig', [
            'form' => $form->createView(),
            'flow' => $flow,
        ]);

Twig Template:

                    <div class="col-md-9">
                        {{ form_start(form) }}
                        {{ form_row(form._token) }}
                        {{ form_errors(form) }}

                        {% if flow.getCurrentStepNumber() == 1 %}
                            <div class="row mt-3">     
                                <div class="col-md-6">
                                    {{ form_row(form.email.first) }}
                                </div>
                                <div class="col-md-6">
                                    {{ form_row(form.email.second) }}
                                </div>
                                <div class="col-md-6">
                                    {{ form_row(form.password.first) }}
                                </div>
                                <div class="col-md-6">
                                    {{ form_row(form.password.second) }}
                                </div>
                            </div>
                            <div class="row mt-2 mb-5">    
                                <div class="col-md-6">
                                    <i class="fas fa-globe-europe"></i> {{ form_label(form.nazione) }}
                                    {{ form_widget(form.nazione) }}
                                    <small>{{ form_help(form.nazione) }}</small>
                                    <div class="form-error">
                                        {{ form_errors(form.nazione) }}
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <i class="fas fa-phone"></i> {{ form_label(form.telefono) }}
                                    {{ form_widget(form.telefono) }}
                                    <small>{{ form_help(form.telefono) }}</small>
                                    <div class="form-error">
                                        {{ form_errors(form.telefono) }}
                                    </div>
                                </div>
                            </div> 
....
                        {% include '@CraueFormFlow/FormFlow/buttons.html.twig' with {
                                craue_formflow_button_class_last: 'btn btn-sm btn-success m-2',
                                craue_formflow_button_class_back: 'btn btn-sm btn-secondary m-2',
                                craue_formflow_button_class_reset: 'btn btn-warning',
                                craue_formflow_button_label_back: 'Indietro',
                                craue_formflow_button_label_next: 'Avanti',
                                craue_formflow_button_label_finish: 'Concludi Registrazione',
                                craue_formflow_button_render_reset: false

                            } 
                        %}
                        {{ form_end(form) }}

Entity:

/**
 * @ORM\Entity(repositoryClass=AccountRepository::class)
 */
class Account implements UserInterface
{

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     * @Assert\NotNull(message="La password non può essere vuota")
     * @Assert\NotBlank(message="La password non può essere vuota")
     */
    private $email;

    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     * @Assert\NotBlank(message="La password non può essere vuota")
     * @Assert\Regex(pattern="/^(?=.*[a-z])(?=.*\d).{8,}$/i", message="La password deve essere di minimo 8 caratteri e deve includere sia una lettera che un numero")
     */
    private $password;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $nazione;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank(message="Il telefono è obbligatorio")
     * @Assert\Length(
     *      min = 2,
     *      max = 50,
     *      minMessage = "Your first name must be at least {{ limit }} characters long",
     *      maxMessage = "Your first name cannot be longer than {{ limit }} characters",
     *      allowEmptyString = false
     * )
     */
    private $telefono="";
...

Could anyone help me?

craue commented 4 years ago

You need to add the correct validation group to all annotations. 😏

migmax48 commented 4 years ago

Thanks for the reply. I added this on the form:

public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => Account::class, 'validation_groups' => ['signup'], ]); }

I added this on the entity

` /**

but nothing changes

migmax48 commented 4 years ago

Solved. I've added this elemnt on flow

    protected function loadStepsConfig() {
        return [
            [
                'label' => 'Dati Account',
                'form_type' => SignupFormType::class,
                'form_options' => [
                    'validation_groups' => ['signup'],
                ],
            ],

Thank you!

craue commented 4 years ago

see https://github.com/craue/CraueFormFlowBundle#validation-groups