Jak na „vložené“ formuláře?

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

V aplikaci potřebuji na několika místech pracovat entitou „company“, data jsou v DB a přísluší k ní formulář. Problem je, že s tímto formulářem potřebuji pracovat na různých místech, například v „oznámení“ nebo při správě „vztahů“.

Požadavek je aby měl uživatel možnost přidávat společnosti „bez mezikroku“, tzn, ve formuláři kde se vytváří oznámení, chci mít možnost vložit formulář z této „company“, verzování a našeptávač mám vytvořený. problém je toto „embedování“ formuláře.

moje představa jak by to mělo fungovat je:

<?php
class Company extends Component {
  public function creteComponentCompanyForm() {
    $f = new AppForm;
    // přidám potřebné prvky
    return $f;
  }
  // další metody zaopuzdřující vazbu na model a zpracování signálů
}
?>

A pak v presenteru:

<?php
class AnnocePresenter extends BasePresenter {
  public function createComponentAnnonceForm(){
    $f = new AppForm;
    $f->addText(...); /// detaily týkající se oznámení
    // a teď bych chtěl přidat práci s formulářem od componenty company
    // něco na styl
    $company = new Company;
    $f->addComponent($company->createComponentCompanyForm());
    return $f;
  }
}
?>

Je možné to nějak vyřešit? nebo budu muset všude vkládat stejný kód okolo „companyForm“ ?

Editoval klok (3. 1. 2010 22:00)

Klokan
Člen | 47
+
0
-

Ten formulář si vytvoř někde bokem jako komponentu, ne přímo v presenteru:

<?php
class FormXX extends AppForm
{
 ...... Kod formulare
}

class CompanyPresenter
{
    protected function createComponentFormXX($name)
    {
        return new FormXX($this,$name);
    }
}
?>

V presenteru se pak na komponentu můžeš odkazovat přes $this->getComponent(‚FormXX‘),
popř. v šabloně widget FormXX

klok
Člen | 11
+
0
-

Zdar bracha :)

Tohle ja nechci, ja chci abych ten formulář mohl přidat do dalšího formuláře, jako jeho soucast.

napr.

Oznameni--------------+
-text                 |
-datum                |
-spolecnost --------+ |
--jmeno spolecnosti | |
--ico spolecnosti   | |
--------------------+ |
----------------------+

A protoze je pozadavek na vytvareni „on fly“ a na vice mistech tak chci ten formular spolecnosti mit jako komponentu vlozitelnou do formulare jako jeho soucast.

Snad to je takhle jasnejsi.

Editoval klok (4. 1. 2010 17:07)

bazo
Člen | 620
+
0
-

html neumoznuje mat v tagu form vlozeny dalsi form

klok
Člen | 11
+
0
-

bazo napsal(a):

html neumoznuje mat v tagu form vlozeny dalsi form

Ale ja nechci v HTML mit vnorene formulare. Nic takoveho jsem nepsal.
Me zajima jak v Nette implementovat cast formulare ktera by byla vlozitelna do vice ruznych formularu aniz bych musel vsude opakovat ten samy kod.

Je mi jasne, ze budu muset zpracovat submit formulare rucne a osetrit tam to co z nej dostanu.

Ale porad nevim jak to zaridit.

Kdyz premyslim o abstrakci, tak by to ve vysledku mohlo byt implementovano jako samostatny control ktery se vlozi do formulare.

bazo
Člen | 620
+
0
-

tak co potom takto:

<?php
function pridajForm($form)
{
	$form->addText()...
	return $form;
}
?>

pricom argument je form, do ktoreho to chces pridat

Filip Procházka
Moderator | 4668
+
0
-

Jenom trochu kosmetiky :)

function pridajForm(&$form)
{
        $form->addText(...);
	...
	// nemusim nic vracet :)
}
klok
Člen | 11
+
0
-

Jo to je možná cesta.

Problem je, ze se tam budou dost tezko zarizovat reakce na signaly.
Ta cast by mela byt schopna napr. kdyz zacne uzivatel vyplnovat ICO spolecnosti
tak na to reagovat a navizet mu ze stavajicich.

Idealni by bolo taky mit moznost povesit se na submit toho nadrazeneho formu.
Ze bych misto udaju z toho formulare dostal id spolecnosti z DB

Mozna to udelat jako samostatny control.

Ondřej Mirtes
Člen | 1536
+
0
-

Ta reference není v případě objektů potřeba, return také ne.

Filip Procházka
Moderator | 4668
+
0
-

Ondřej Mirtes: Dobrý vědět :D jdu si asi dostudovat základy :)

Cifro
Člen | 245
+
0
-

Alebo ja som videl aj také niečo:

	private function createBaseForm()
	{
		$form = new AppForm();
		$form->addText('title', 'Titulek');
		//..
		return $form;
	}

	protected function createComponentNewForm()
	{
		$form = $this->createBaseForm();
		$form->addSubmit('send', 'Vytvořit článek');
		$form->onSubmit[] = array($this, 'newFormSubmitted');
		//..
		return $form;
	}

	protected function createComponentEditForm()
	{
		$form = $this->createBaseForm();
		$form->addSubmit('send', 'Uložit změny');
		//...
		return $form;
	}

Neviem či to je to čo presne chceš ale je to zaujímavý DRY postup

Klokan
Člen | 47
+
0
-

Ještě mě napadla taková věc, ale nevím jestli to bude ono a zda by to tak vůbec šlo.
Vytvořit si formulář klasicky jako AppForm a pak při vykreslení použít pouze $form->render(‚body‘), aby se vykreslilo jen tělo toho formuláře ?

klok
Člen | 11
+
0
-

Díky všem za rady, až to nějak pořeším tak to dam sem.
Teď se na mě hrne práce z jiné strany takže tohle bude muset jít na chvilku k ledu.

Aurielle
Člen | 1281
+
0
-

Já dědím AppForm a v tom mám spamovou prevenci od Ondřeje a (mimo jiné) funkce ovlivňující ConvectionalRenderer.

PetrP
Člen | 587
+
0
-

Možností je mnoho:

Presenter::createBaseForm(); // jak píše Cifro

nebo

class BaseForm extends AppForm // tedy si ho rozšířit dle potřeby, a do contructoru dát to co by bylo v createBaseForm (píše gmvasek)

Nebo si vytvářet části formuláře úplně zvlášt.

function createCastFormulare()
{
	$fc = new FormContainer();
	$fc->addText(...)
	return $fc;
}

function createComponentForm()
{
	$form = new AppForm();
	$form['cast'] = $this->createCastFormulare();
	...
}

(pozor ze v Form::getValues budes mit hodnoty ještě zanořené do jednoho pole)

//edit: redhead dík

Editoval PetrP (21. 1. 2010 11:22)

redhead
Člen | 1313
+
0
-

jen opravím: máš ‚BaseForm extends BaseForm‘ (má být ‚.. extends AppForm‘) ;)

slapo
Člen | 22
+
0
-

Zdravím,

ako by sa dala

$form['cast']

pridať do nejakej skupiny (teda aby sa skupina polí dostala do tagu fieldset)?

Skúsil som niečo ako:

$form = new AppForm();
$form->addGroup('Skupina', true);
$form['cast'] = $this->createCastFormulare();
$form->addSubmit('form_submit', 'Odoslať');
...

ale veľmi to nepomohlo – do skupiny sa dostalo len tlačidlo ‚Odoslať‘ a obsah $form[‚cast‘] skončilo pod tým.
Metóda FormContainer() neobsahuje addGroup, takže to asi pôjde nejako inak, len som zatiaľ nenašiel ako.
Ak viete, prosím, poraďte.

Ďakujem :)

Editoval slapo (30. 3. 2010 16:17)

slapo
Člen | 22
+
0
-

Skúšal som aj

$form->addGroup('Skupina', true)->setOption('embedNext', TRUE);

ale ani tak sa mi nepodarilo dostať komponenty z $form[‚cast‘] do žiadnej skupiny.
Nemáte niekto tip?

Ďakujem.

Mikulas Dite
Člen | 756
+
0
-

Tipoval bych to na

$form['cast'] = $this->createCastFormulare();
$form['cast']->addGroup('Skupina', true);

\\Edit: máš pravdu, já si to nepřečet. FormContainer to neumí. Vůbec se mi zdá takový zanedbaný…

Editoval Mikulas Dite (6. 4. 2010 16:51)

Honza Kuchař
Člen | 1662
+
0
-

@PetrP: to je to správné řešení! A dokonce můžeš i zpracovávat data…

class MyPresenter extends Presenter {

	function createSekceFormulare() {
		$f = new FormContainter();
		$f->getForm()->onsubmit[] = function(Form $f) {
			Debug::dump($f->values);
		}
		return $f;
	}

	function createComponentForm($name) {
		$f = new AppForm($this,$name);
		$f["skupina"] = $this->createSekceFormulare();
	}

}

Editoval honzakuchar (6. 4. 2010 18:11)

slapo
Člen | 22
+
0
-

Mikulas Dite napsal(a):

Tipoval bych to na

$form['cast'] = $this->createCastFormulare();
$form['cast']->addGroup('Skupina', true);

\\Edit: máš pravdu, já si to nepřečet. FormContainer to neumí. Vůbec se mi zdá takový zanedbaný…

Je to škoda, pretože potom by sa dalo iterovať cez skupiny, prípadne si ich umiestniť podľa ľubovôle.
Aj tak ďakujem za pokus :)

Editoval slapo (12. 4. 2010 12:05)