Jak funguje createcomponent

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

Zdravím,
při čtení fóra jsem si všiml, že se create component dá psát více způsoby. Zajímalo by mě jaký je rozdíl mezi zápisem:

protected function createComponentForm($name)
{
	$form = new \Nette\Application\AppForm($this, $name);
	...
	return $form;
}

a kódem:

protected function createComponentForm()
{
	$form = new \Nette\Application\AppForm;
	...
	return $form;
}

Ještě by mě zajímalo kdy přesně je metoda createComponentFrom volána a co dostane v parametru $name. Pak jsem si ještě všiml, že existuje metoda createComponent($name), ale u té vůbec nevím k čemu slouží a jak se používá.

Patrik Votoček
Člen | 2221
+
0
-

rozdíl mezi první a druhou variantou je ten že u první je komponenta ihned spojena s presenterem. kdežto u druhého až později.

A createComponentXxxXxx se volá automaticky pokud se pokusíš ke komponentě přistoupit. Tj. v presenteru $this[‚xxxXxx‘] nebo v šabloně {widget xxxXxx} / {control xxxXxx} / {!$presenter['xxxXxx']...}.
A v $name máš právě to xxxXxx. A createComponent($name) je vpodstatě takový obal nad super továrničkama (createComponentXxxXxx je super továrnička pro jednu komponentu a createComponent($name) globální továrnička).

Editoval vrtak-cz (5. 2. 2010 9:02)

JajazXbm
Člen | 29
+
0
-

Díky za odpověď, ale ještě mi to není úplně jasné.

rozdíl mezi první a druhou variantou je ten že u první je komponenta ihned spojena s presenterem. kdežto u druhého až později.

Co znamená ihned? a co znamená později? kdy později? později za hodinu? nebo později v dalším běhu skriptu? nebo kdy?

Nějak se mi to trošku míchá, kdysi jsem četl, že v metodě renderCosik nemůžu vytvářet formuláře, protože už je pozdě. Podle toho co píšeš se v metodě render použije $this['form'] a v tu chvíli se zavolá createComponentForm. Jak to, že není pozdě?

Poslední věc… Mám li metodu createComponentForm udělám {widget form} tak se zavolá moje metoda a dostane parametr form? Na co? K čemu to je, když už to jméno je předem jasné z toho názvu metody?

Editoval JajazXbm (5. 2. 2010 9:13)

norbe
Backer | 405
+
0
-
  1. Ihned znamená po vytvoření objektu. Později znamená po ukončení metody createComponentXxx (tedy po return $komponenta;).
  2. Pokud formuláře vytváříš v komponentě, pozdě to není (pozdě to je pouze pokud by jsi v renderXxx formulář ještě upravoval – to funguje správně pouze v actionXxx nebo přímo v továrničce).
  3. To je k tomu, aby se ti jednodušeji měnil název komponenty (stačí změnit název továrničky a nemusíš upravovat její kód).
JajazXbm
Člen | 29
+
0
-

norbe napsal(a):

1. Ihned znamená po vytvoření objektu. Později znamená po ukončení metody createComponentXxx (tedy po return $komponenta;).

Takže z praktického hlediska v tom nevidím žádný rozdíl.

2. Pokud formuláře vytváříš v komponentě, pozdě to není (pozdě to je pouze pokud by jsi v renderXxx formulář ještě upravoval – to funguje správně pouze v actionXxx nebo přímo v továrničce).

Nevidím v tom rozdíl. Buď vytvořím formulář přímo v metodě renderCosik, nebo v metodě render cosik použiju $this['form'] což je v podstatě zavolání metody, která zavolá jinou metodu, která zavolá createComponentForm. Nevidím v tom vůbec žádný rozdíl, vždyť je to stejné.

>

3. To je k tomu, aby se ti jednodušeji měnil název komponenty (stačí změnit název továrničky a nemusíš upravovat její kód).

To sice ano, ale ptal jsem se k čemu je to předávané jméno v tom parametru name.

jasir
Člen | 746
+
0
-

JajazXbm napsal(a):

norbe napsal(a):

2. Pokud formuláře vytváříš v komponentě, pozdě to není (pozdě to je pouze pokud by jsi v renderXxx formulář ještě upravoval – to funguje správně pouze v actionXxx nebo přímo v továrničce).

Nevidím v tom rozdíl. Buď vytvořím formulář přímo v metodě renderCosik, nebo v metodě render cosik použiju $this['form'] což je v podstatě zavolání metody, která zavolá jinou metodu, která zavolá createComponentForm. Nevidím v tom vůbec žádný rozdíl, vždyť je to stejné.

Je v tom rozdíl. Pokud vytvoříš formulář v renderXXX, (tzn new AppForm ...), nemůže přijímat signály, protože ve fázi zpracování signálu není ještě vytvořená.

Pokud použiješ továrničku, formulář/komponenta je vytvořena v okamžiku, kdy je potřeba. To je většinou
až v render, ale při přijímání signálu dříve.

>

3. To je k tomu, aby se ti jednodušeji měnil název komponenty (stačí změnit název továrničky a nemusíš upravovat její kód).

To sice ano, ale ptal jsem se k čemu je to předávané jméno v tom parametru name.

Vždyť ti to norbe napsal.

Editoval jasir (5. 2. 2010 10:25)

JajazXbm
Člen | 29
+
0
-

>

3. To je k tomu, aby se ti jednodušeji měnil název komponenty (stačí změnit název továrničky a nemusíš upravovat její kód).

To sice ano, ale ptal jsem se k čemu je to předávané jméno v tom parametru name.

Vždyť ti to norbe napsal.

Tak nevím, jestli nerozumíte vy mně, nebo já vám. Jo tak chápu, ale dalo mi to.

Ještě by mě teda zajímala poslední věc. Je teda rozdíl mezi tím, jestli je formulář připojen k presenteru ihned, nebo až později?

Ondřej Mirtes
Člen | 1536
+
0
-

createComponentXXX() se zavolá při prvním zavolání $this['XXX'] ($this->getComponent('xxx')). Na vytváření formuláře v render fázi je pozdě, protože když pak má přijímat signál (zavolat submitovací metodu), tak ho v té fázi (před render) Presenter vůbec nevidí a tak neví, jakou metodu má zavolat. Kdežto když použiješ továrničku, tak doba, kdy se formulář vytvoří, je v rukou Presenteru a on si formulář při přijímání signálu vytvoří sám. První „tvoje“ volání $this->getComponent('xxx') tak může být klidně až v šabloně a ničemu to nevadí.

Základní podoba továrničky, kterou doporučuji používat, je tato (je s ní nejmíň psaní):

protected function createComponentName() {
	$form = new AppForm;
	//...
	return $form;
}

Pak můžeš použít takový ošklivý hybrid (který nedoporučuji :)):

protected function createComponentName() {
	$form = new AppForm($this, 'name');
	//...
	return $form;
}

Tvar s parametrem:

protected function createComponentName($name) {
	$form = new AppForm($this, $name); //dokud se metoda bude jmenovat createComponentName, v parametru $name bude vždy 'name'
	//...
	return $form;
}

K čemu je připojení k Presenteru hned ve fázi vytvoření objektu AppForm? Nyní to má už menší význam, než dříve (formuláře prodělaly pár změn, např. bez připojení k Presenteru kdysi nešlo volat setDefaults), ale hodí se to, pokud chceš v továrničce přenastavovat cestu, kam se formulář odešle ($form->action). Při nastavování už musí být připojen k Presenteru, jinak by se ti po připojení ta nastavená cesta přepsala.

A metoda createComponent($name)? Dříve ve frameworku existovala jen ona (měla podobu velkého switche, kde jsi vyjmenovával ty jednotlivé komponenty, které jsi vytvářel), dnes ve třídě Presenteru zastává funkci volání těchto supertovárniček createComponentXXX(). Znamená to tedy, že když si např. v BasePresenteru překryješ metodu createComponent($name), supertovárničky ti přestanou funkgovat.

JajazXbm
Člen | 29
+
0
-

Super, díky všem za vyčerpávající odpovědi.

_Martin_
Generous Backer | 679
+
0
-

Ondřej Mirtes napsal(a):

A metoda createComponent($name)? Dříve ve frameworku existovala jen ona (měla podobu velkého switche, kde jsi vyjmenovával ty jednotlivé komponenty, které jsi vytvářel), dnes ve třídě Presenteru zastává funkci volání těchto supertovárniček createComponentXXX(). Znamená to tedy, že když si např. v BasePresenteru překryješ metodu createComponent($name), supertovárničky ti přestanou funkgovat.

Jenom bych dodal, že její překrytí se občas využívá ve speciálních případech, kdy chceš například jednu podobnou komponentu vykreslit vícekrát. Potom do té metody přidáš vlastní logiku a případně budeš volat předka (pro supertovárničky) – ale to už je taková vyšší dívčí=)

radvis
Začátečník | 110
+
0
-

Já používám tohle:
` protected function createComponent($name)
{
switch ($name) {

case ‚InzeratyForm‘:

$Inzeraty = new AppForm($this, $name);

$Inzeraty->addSelect(„sekce“, „Vyberte:“, $sekce)
->addRule(Form::FILLED, ‚Vyplňte prosím nkam chcete inzerát přidat.‘);

$Inzeraty->addText(‚title‘, ‚Nadpis:‘)
->addRule(Form::FILLED, ‚Vyplňte prosím nadpis.‘);

$Inzeraty->addProtection(‚Please submit this form again (security token has expired).‘);

$Inzeraty->onSubmit[] = array($this, ‚poptavkaFormSubmitted‘);

return $Inzeraty;

default:
parent::createComponent($name);
}

}`
Je to dobře?

Patrik Votoček
Člen | 2221
+
0
-

radvis napsal(a):

ehm přečti si https://forum.nette.org/…iewtopic.php?… a když už v tom budeš tak i https://forum.nette.org/…iewtopic.php?…

Editoval vrtak-cz (6. 2. 2010 12:09)

PetrP
Člen | 587
+
0
-

radvis napsal(a):

Já používám tohle:

	protected function createComponent($name)
	{
		switch ($name) {

		case 'InzeratyForm':

		$Inzeraty = new AppForm($this, $name);

		$Inzeraty->addSelect("sekce", "Vyberte:", $sekce)
		         ->addRule(Form::FILLED, 'Vyplňte prosím nkam chcete inzerát přidat.');

		$Inzeraty->addText('title', 'Nadpis:')
		         ->addRule(Form::FILLED, 'Vyplňte prosím nadpis.');

		$Inzeraty->addProtection('Please submit this form again (security token has expired).');

		$Inzeraty->onSubmit[] = array($this, 'poptavkaFormSubmitted');

		return $Inzeraty;

		 default:
	 parent::createComponent($name);
}

	}

Je to dobře?

Není.

A taky lépe formatuj kód v příspěvků viz: https://forum.nette.org/…iewtopic.php?…

Editoval PetrP (18. 2. 2010 16:55)