craue / CraueFormFlowBundle

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

Two form types with two different data classes #354

Closed cooldude77 closed 3 years ago

cooldude77 commented 4 years ago

Hi, I have a form type

class CategoryChooserForm extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add("businessCategory", ChoiceType::class,
            [
                'required' => true,
                'choices' => [
                    'Cat1' => null,
                    'Yes' => true,
                    'No' => false,
                ]
            ]);
    }

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

and

class BusinessNameForm extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add("businessName", TextType::class, ['required' => true])
            ->add("useName", CheckboxType::class, ['mapped' => false]);
    }

    /**
     * @param OptionsResolver $resolver
     * @throws \Symfony\Component\OptionsResolver\Exception\AccessException
     */

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

Data Classes

class BusinessNameFormDataClass
{

    private $businessName;

    /**
     * @return mixed
     */
    public function getBusinessName()
    {
        return $this->businessName;
    }

    /**
     * @param mixed $businessName
     */
    public function setBusinessName($businessName)
    {
        $this->businessName = $businessName;
    }

}

and

class CategoryChooserFormDataClass
{

    private $businessCategory;

    /**
     * @return mixed
     */
    public function getBusinessCategory()
    {
        return $this->businessCategory;
    }

    /**
     * @param mixed $businessCategory
     */
    public function setBusinessCategory($businessCategory)
    {
        $this->businessCategory = $businessCategory;
    }

}

Flow class

class PostBusinessSignUpFlowService extends FormFlow
{

    protected function loadStepsConfig()
    {
        return [
            [
                'label' => 'Choose Category',
                'form_type' => CategoryChooserForm::class,
            ],
            [
                'label' => 'Business Name',
                'form_type' => BusinessNameForm::class,

            ],
        ];
    }

}

Controller


class PostSignUpWizardController extends Controller
{

    /**
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \InvalidArgumentException
     * @throws \LogicException
     */
    public function wizardAction()
    {

        $flow = $this->get('business_main.service.sign_up_wizard'); // must match the flow's service id
        $formData = new CategoryChooserFormDataClass(); // Your form data class. Has to be an object, won't work properly with an array.

        $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('@BusinessMain/Wizard/post_sign_up_wizard.html.twig', [
            'form' => $form->createView(),
            'flow' => $flow,
        ]);
    }

}

Step 1 render goes fine

But upon pressing next , I get the error

The form's view data is expected to be an instance of class Business\MainBundle\Form\DataClass\BusinessNameFormDataClass, but is an instance of class Business\MainBundle\Form\DataClass\CategoryChooserFormDataClass. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms an instance of class Business\MainBundle\Form\DataClass\CategoryChooserFormDataClass to an instance of Business\MainBundle\Form\DataClass\BusinessNameFormDataClass. So my question is how to configure flow/controller in order to make use of two forms with different data_class? Thanks

RootProgger commented 4 years ago

is there any solution for that? i have the same problem...

progzy commented 4 years ago

I think you should use one DTO and remove your 'data_class' keys.

craue commented 3 years ago

@progzy is right. See #28.