Zachycení akce formuláře v přesenteru před createComponent

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Jabqooo
Člen | 3
+
0
-

Zdravím,
nikde jsem tu nenašel odpověď, tak se zkusím zeptat takto.
Mám formulář s dynamickým přidáváním firem (obsahující kontakt, adresu, Ičo, …) pomocí tlačítka. Formulář má ještě jedno tlačítko pro uložení. Uložení probíhá ok, ale přidání formuláře mi bohužel nefunguje. Respektive nevím jak docílit toho abych v presenteru přidal další název (pro další kontejner – firmu) před createComponent.

Na vytváření formuláře mám továrničku které předávám callback, počet firem a názvy kontejnerů pro jednotlivé firmy(oddělovačem je čárka). Poprvé se počet firem přidá podlě $count a následně bych chtěl aby to bylo podle počtu v $name. Zde jsou názvy kontejnerů plus by zde měl být nový název nového kontejneru.

`

<?php
public function create(array $callback, $count, $name)
{
	class FormFirmFactory extends Object
	{
		$form = new Form;

		//for add firm
		if ($name !== null) {
			$names = explode(',', $name);
		} else {
			$names = [];
		}

		$formNames = $form->addHidden('names');

		$form->addHidden('onlyadd');

		if (count($names) > 0) {
			foreach ($names as $nam) {
				$this->addComponent($nam, $form);
			}
			$formNames->setValue($nam);
		} else {
			for ($i = 1; $i <= $count; $i++) {
				$nam = 'firm' . substr(md5($i), -4);
				$names[] = $nam;
				$this->addComponent($nam, $form, $i);
			}

			$formNames->setValue(implode(',', $names));
		}

		$form->addSubmit('submitAddFirm', 'Přidat firmu');
		$form->addSubmit('submitFirm', 'Uložit a pokračovat');
		$form->onSuccess[] = $callback;
		return $form;
	}


	private function addComponent($name, Form $form, $i = null)
	{
		$firmContainer = $form->addContainer($name);

		$firmContainer->addText('name', "Název")
			->setHtmlId('name')
			->addRule(Form::MAX_LENGTH, 'Max length is %d', 64)
			->addConditionOn($form['onlyadd'], $form::NOT_EQUAL, '1')
				->addRule(Form::FILLED);

		$firmContainer->addText('address', "Adresa")
			->addCondition(Form::FILLED)
				->addRule(Form::MAX_LENGTH, 'Max length is %d', 250);

		$firmContainer->addText('in', "IČO")
			->addRule(Form::MAX_LENGTH, 'Max length is %d', 10);

		$firmContainer->addText('tin', "DIČ")
			->addRule(Form::MAX_LENGTH, 'Max length is %d', 12);

		$firmContainer->addText('contact', "Kontakt");
	}
}
?>

`

Pokud přidám tlačítkem firmu tak se odešle formulář, presenter zachytí signál v metodě submitFirm, kde jsem chtěl vytvořit další jméno pro kontejner firmy. Ale to už je komponenta vytvořena, takže je to pozdě. A komponenta se vytvoří stejná jako předtím. A při dalším kliknutí jsou tam logicky hodnoty z minula.

`

<?php
final class NewDocumentPresenter extends BasePresenter
{

	/** @var string @persistent */
	public $firms;

	public function submitFirm(Form $form)
	{
		$values = $form->getValues(true);
		if($values['onlyadd'] == '1') {
			$this->names = $values['names'] . ($values['names'] ? ',' : '') . 'firm' . substr(md5(date("d.m.Y G:i:s")), -4);
			$this->redrawControl();
		} else {
			//tady je ukladani
		}
	}

	protected function createComponentFirm()
	{
		$form = $this->firmService->getFirm([$this, 'submitFirm'], $this->names, $this->count);
		$form->onError[] = function ($form) {
			$this->redrawControl();
		};

		return $form;
	}
}
?>

`

Mohl by mi prosím někdo poradit jak by se toto mělo řešit. Potřebuji nějak zjistit, že uživatel chce přidat firmu (stisklo se tlačítko přidat firmu) ještě před tím, než se zavolá createComponent.

Kód jsem očesal od zbytečností, aby byl přehlednější. zde je ještě část ze servisy, která se volá z presenteru. Šablonu mi přijde zbytečné sem dávat, ale pokud si myslíte opak, není problém dodat ;-).
`

<?php
	public function getFirm($callback, $names, $count)
	{
		$firmFactory = new FormFirmFactory();
		return $firmFactory->create($callback, $count, $sides);

	// mimo toto se zde ještě načítají ještě nějaké hodnoty a doplňují defaultní hodnoty pro prvky formuláře
	}
?>

`

Ješte jednou díky za jakoukoliv radu, zavařil jsem se na tomhle na půl dne.

Jiří Nápravník
Člen | 710
+
+1
-

Nevím, jestli to úplně chápu, ale mrkni na Kdyby\Replicator ten řeší dynamický počet položek.

Jabqooo
Člen | 3
+
0
-

Ahoj, díky ale asi kvůli této jedné prkotině nebudou přidávat do produkčního softu závislost na Kdyby replikatoru.
Proto mě zajímalo jak vyřešit (pokud to tedy nějak jde) zachycení odeslaného formu presenterem dřív, než se zavolá createComponent.
Jestli to dobře chápu životní cyklus, tak se odeslaný form zachytí v handle a createComponent pokud ho poprvé potřebuji. Tzn, pokud mám v šabloně toto:

<form n:name=firm class=„form ajax“> …

, tak jsem čekal že createComponen se provede v render, ale očividně je to dřív než v handle. Takže se create component potřebuje již někde dřív a nebo něco dělám blbě (což nevylučuji).

Samozřejmě by to šlo ohekovat tak, že si data z formuláře uložím nejen po stisknutí tlačítka uložit, ale i po stisknutí tlačítka přidat. Ale to je podle mě špatné řešení a tak se tomu snažím vyhnout.

Jabqooo
Člen | 3
+
0
-

Nakonec jsem to vyřešil tak, že v metodě submitFirm volám metodu, která do formu přidá další komponentu s firmou.
Nevěděl jsem že v okamžiku, kdy handle zachytí submit a createComponent již vytvořil form, tak mohu ještě do formu v klidu hrabat ;-). Jo a názvy jednotlivých komponent z formu si nakonec ukládám do session.

`

<?php

    public function submitFirm(Form $form)
    {
        $values = $form->getValues(true);
        if($values['onlyadd'] == '1') {
            $newName = 'firm' . substr(md5(date("d.m.Y G:i:s")), -4);

			$this->formFirmFactory->addComponent($newName, $form)

            $this->redrawControl();
        } else {
            //tady je ukladani
        }
    }


?>

`