Merge two or more forms into one

5 months ago

iwory
Member | 147
+
0
-

Hello, is there some way how to merge forms?

I have four separate forms for the edit but in one case I need to merge them into one. Is it possible to do that?

class OneForm extends Form
{

    public function __construct()
    {
        // Big logic of form here
        $this->addText('foo', 'Foo');
    }
}
class SecondForm extends Form
{

    public function __construct()
    {
        // Big logic of form here
        $this->addText('foo2', 'Foo2');
    }
}
....
class MyForm extends UI/Control
{

    public function createComponentForm()
    {
        $form = new UI/Form();
        $oneForm = new OneForm();
        $secondForm = new SecondForm();

        $form->someFunctionOrAnythingElse($oneForm);
        $form->someFunctionOrAnythingElse($secondForm);

        ...
    }
}

4 months ago

Isigarek
Member | 69
+
0
-

Sorry for late response but i found that now and sorry for my bad english.
If you have form component you can use function

$form->getComponents()

that will with all form inputs

return Nette\ComponentModel\RecursiveComponentIterator

For me:

Nette\ComponentModel\RecursiveComponentIterator #8378
city => Nette\Forms\Controls\TextInput #3921
street => Nette\Forms\Controls\TextInput #1064
psc => Nette\Forms\Controls\TextInput #1199
country => Nette\Forms\Controls\SelectBox #44fe

Now its easy you have to foreach iterator and set new components into new form but there is one problem that you have to set new parent to them.

This is example work but i dont think that this is good path to get this…

protected function createComponentAdd()
    {
        $form = new Form();
        $form->addText("name","Název")
            ->setRequired("Název pobočky musíte vyplnit...");
        $form->addTextArea("description","Popis pobočky",3,3)
            ->setRequired(false);
        $form->addSubmit("submt","Přidat pobočku");

        //$this["adress"] is adress component that i create bellow and function getForm is function which returns form object from adress component
        $components = $this["adress"]->getForm()->getComponents(true);

        foreach($components as $item => $object)
        {
            $form[$item] = $object->setParent($form->getParent(),$form->getName());
        }

        //After that you have merge forms


        $form->onSuccess[] = function($val){
            Dumper::dump($val);
        };
        return $form;
    }

    //My second component with form
    protected function createComponentAdress()
    {
        $adress = new adressAddComponent($this->core);
        return $adress;
    }

PS: Pokud někdo najde jakoukoliv chybu v Angličtině budu moc rád pokud ji opraví či ji napíše. A popřípadě upraví i možnosti tohoto řešení, protože jsem jiné nenašel.

4 months ago

Isigarek
Member | 69
+
0
-

So i create function for this…

/**
     * @param Form|null $baseForm
     * @param array ...$forms
     * @return Form
     * @throws \Exception
     */
    public function mergeForms(Form $baseForm = null, ...$forms)
    {
        if(is_array($forms))
        {
            $components = [];
            $form = new Form();
            foreach($forms as $object)
            {
                if($object instanceof Form)
                {
                    $listOfComponents = $object->getComponents();
                    foreach($listOfComponents as $id => $component)
                    {
                        $components[$id] = $component->setParent($baseForm->getParent());
                        $form[$id] = $component->setParent($baseForm->getParent());
                    }
                }
                else
                {
                    throw new \Exception("Object is not form");
                }
            }
            return $form;
        }
        else
        {
            throw new \Exception("Second parameter must be type of array");
        }
    }

Usage is quite simple…

$mergeForm = $this->mergeForms($baseForm,$form1,$form2,$form...);

It's return form with all componenents from form1,form2 and next forms and parent take from $baseForm so you can use one form and extended by components only from another…