craue / CraueFormFlowBundle

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

Dynamic Adding/removing Steps from Flow - dependant on Previous Step #289

Open silentgecko opened 7 years ago

silentgecko commented 7 years ago

Hello,

my case is: Step1: Input Field with Integer of Number of Adults - min 1 - max 10 Step2-N: Dynamic Number of Steps, dependant on how many Adults you putted in in Step1.

But i'm not able to do it with the nice way. I tried GetSteps Event - problem here is that i don't have the real formData - only initial Object Data I tried PostBindSavedDataEvent - problem here is i can't manipulate the steps anymore.

So the only possible way is i create a form flow with 11 Steps, each time with a skip dependancy. But now i've to change the Stepconfig every single time when i want to change the max. limit on the integer field. That's not how it should work.

Is it possible to create a dynamic amount of steps, for e.g. after submitting the first step?

tomasjav commented 7 years ago

Did you find a solution by any chance? I have the same problem now.

silentgecko commented 7 years ago

no, i did not found any better solution than i wrote: add as much substeps as you need on creation, and skip the steps dependant on your form inputs. but take care of the generated navigation, it will show then for e.g. step1, step2, step23, step24 or sth :D

rsida commented 3 years ago

I would recommend creating a FormType (or many) and implementing EventSubscriberInterface and listening on FormFlowEvents::GET_STEPS event. Then on this event, you could get all existing step, create manually a new one and insert it before or after a step based on FormData.

rsida commented 3 years ago

Here an example that you could used:

<?php

namespace AppBundle\Form\Type;

use AppBundle\Form\Flow\MyCustomFormFlow;
use Craue\FormFlowBundle\Event\GetStepsEvent;
use Craue\FormFlowBundle\Form\FormFlowEvents;
use Craue\FormFlowBundle\Form\Step;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\AbstractType;

class ListingNewStepOneType extends AbstractType implements EventSubscriberInterface
{
    ...

    public function onGetSteps(GetStepsEvent $event): void
    {
        $flow = $event->getFlow();
        if (!$flow instanceof MyCustomFormFlow) {
            return;
        }
        $steps = $event->getSteps();
        $step = new Step();
        $step->setNumber(count($event->getSteps()) + 1);
        $step->setFormType(static::class);
        $step->setFormOptions(['validation_groups' => ['Default', 'default_groupe']]);
        $step->setLabel('Step X');
        $steps[] = $step;
        $event->setSteps($steps);
    }

    public static function getSubscribedEvents(): array
    {
        return [
            FormFlowEvents::GET_STEPS => ['onGetSteps'],
        ];
    }
}
VLynnik commented 2 years ago

Here an example that you could used:

<?php

namespace AppBundle\Form\Type;

use AppBundle\Form\Flow\MyCustomFormFlow;
use Craue\FormFlowBundle\Event\GetStepsEvent;
use Craue\FormFlowBundle\Form\FormFlowEvents;
use Craue\FormFlowBundle\Form\Step;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\AbstractType;

class ListingNewStepOneType extends AbstractType implements EventSubscriberInterface
{
    ...

    public function onGetSteps(GetStepsEvent $event): void
    {
        $flow = $event->getFlow();
        if (!$flow instanceof MyCustomFormFlow) {
            return;
        }
        $steps = $event->getSteps();
        $step = new Step();
        $step->setNumber(count($event->getSteps()) + 1);
        $step->setFormType(static::class);
        $step->setFormOptions(['validation_groups' => ['Default', 'default_groupe']]);
        $step->setLabel('Step X');
        $steps[] = $step;
        $event->setSteps($steps);
    }

    public static function getSubscribedEvents(): array
    {
        return [
            FormFlowEvents::GET_STEPS => ['onGetSteps'],
        ];
    }
}

@rsida this code does not create a new step in the form.