Jak vytvářet komponenty až když jsou potřeba, (asi) bez továrničky?

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

Ahoj,

poradil by mi někdo, jak vytvářet komponenty, až když jsou skutečně potřeba (tak jako to dělá právě továrnička), když ale dopředu neznám jaké budou? Tzn. tak nějak dynamicky.

V šabloně bych měl třeba {control list}, {control sidebar} apod., nemůžu ale vytvořit továrničky v presenteru, protože nevím jaké komponenty na stránce budou (a nechce se mi tedy ani do presenteru psát createComponent...) Poradil by někdo nějaké rozumné řešení s tím, že by se mi hodilo, kdyby mohlo být více stejných komponent – za použití Multiplieru.

Ve zkratce, u stránek si chci navolit, jaké komponenty u ní budou. Ty komponenty budou formou modulů, můžou se tedy přidávat a psát do kódu createComponentNovyModul při každém přidání nového modulu by asi nebylo ideální :-)

Díky za navedení jak na to, pokud jste třeba už někdo něco podobného řešil, zkoušel jsem i různě hledat, i v kódech, ale nic moc me teď nenapadá…

vvoody
Člen | 910
+
0
-

… nevím jaké komponenty na stránce budou …

A kto to vie? na zaklade coho sa tam tie komponenty vyberu?

Ve zkratce, u stránek si chci navolit, jaké komponenty u ní budou.

Kde/ako si to navolenie predstavujes?

joe
Člen | 313
+
0
-

Pardon, moc hodin :) a nechtěl jsem to dál natahovat. Řekněme, že v presenteru bych měl dostupný seznam komponent (bude se získávat z databáze), které bych chtěl vykreslit (pole komponent může být na každé stránce jiné).

$components = array(
	'list', 'sidebar', 'menu', ...
);

Názvy skutečných tříd by odpovídaly jejich názvům, jen by měly velké první písmeno (List, Sidebar, Menu, apod.).

vvoody
Člen | 910
+
0
-

Maju tie komponenty nejaku funkcionalitu? Netreba im predat ziadne parametre/sluzby? Podla tych nazvov mi to pride tak, ze na to budu stacit len bloky.

duke
Člen | 650
+
0
-

Nejspíš budeš muset překrýt metodu Presenter::createComponent tak, aby ti vytvářela komponenty podle dat z databáze. Bez toho by ti nefungovaly signály. Zbytek by už neměl být problém.

joe
Člen | 313
+
0
-

Díky za rady.

vvoody
Některé moduly budou v základu bez funkce, ale je možné je rozšířit a funkci jim dodat. Z toho důvodu bych je asi nechal být jako komponentami.

duke
Tak jsem si přepsal metodu createComponent jak píšeš, na

protected function createComponent($name) {

	$component = parent::createComponent($name);

	if ($component !== NULL) {
		return $component;
	}

	$ucname = ucfirst($name);
	$class = '\My\Namespace\Modules\\' . $ucname;

	if (class_exists($class)) {

		$component = new Multiplier(function () use($class) {
			$control = new $class;
			return $control;
		});

		$this->addComponent($component, $name);
		return $component;
	}

	return NULL;

}

A když na to teď koukám a snažím se to pochopit, nevím jak je možné že to funguje :-)
Vzhledem k tomu, že i nastavení modulů (komponent) bude v databázi, nastavoval bych je až v době napojení na presenter, tedy při události attached. Je to dobrý nápad?

Nicméně jsem dosáhl toho, co jsem chtěl a to například toho, že si do šablony vložím

{control gallery-nazev}
{control gallery-jinynazev}

a nemusím do presenterů psát metody createComponentGallery

duke
Člen | 650
+
0
-

joe napsal(a):

A když na to teď koukám a snažím se to pochopit, nevím jak je možné že to funguje :-)

Klíčem k pochopení je kód metody Nette\ComponentModel\Container::getComponent a kód třídy Nette\Application\UI\Multiplier.

Vzhledem k tomu, že i nastavení modulů (komponent) bude v databázi, nastavoval bych je až v době napojení na presenter, tedy při události attached. Je to dobrý nápad?

Z praktického hlediska je to v tvém případě možná jedno, ale ideově pokud nastavení komponenty nijak nesouvisí s jejím připojením k jiným komponentám (např. presenteru), není důvod řešit to přes attached.

Mimochodem, pokud se nepletu, je řádek:

	$this->addComponent($component, $name);

… zbytečný, neboť to se provádí automaticky v již zmíněné metodě Nette\ComponentModel\Container::getComponent.

Editoval duke (24. 9. 2012 1:45)

joe
Člen | 313
+
0
-

Máš pravdu, díky. Rychle jsem to debugoval a všimnul si, že to jde přes addComponent, co jsem tam dopisoval. O to víc zvláštní mi přišlo, jak se vytváří ty komponenty „uvnitř“ multiplieru.

To nastavení dělám uvnitř té funkce, kde komponentu vytvářím (komponenta od které všechny budou dědit má setSettings nebo něco podobného), nevím proč jsem to dal do attached… díky za pomoc.

danielseek
Člen | 42
+
0
-

Dobrý den,
narazil jsem na stejnou potřebu jako autor tohoto tématu. Není mi ale jasná úloha tohoto kódu:

$component = new Multiplier(function () use($class) {
            $control = new $class;
            return $control;
        });

Callback předaný Multiplieru by měl přeci fungovat jako factory, která vyplivne různé komponenty podle toho jaký dostane parametr. Změnilo by se něco pokud bych Multiplier úplně vynechal? ->

$control = new $class;
duke
Člen | 650
+
0
-

Díky multiplieru právě funguje:

{control gallery-nazev}
{control gallery-jinynazev}

Tj. konstruuje se nikoli jediná komponenta gallery, ale Multiplier (což je speciální kontejner pro komponenty) pojmenovaný „gallery“, který umí vytvářet předem určeným způsobem různě pojmenované („nazev“, „jinynazev“) subkomponenty. Krom toho se v tomto konkrétním případě název kontejneru, tj. „gallery“, používá k určení třídy, jejíž instance se vytvářejí v Multiplieru.

Bez Multiplieru by ti fungovalo maximálně:

{control gallery}

Editoval duke (26. 1. 2013 22:45)

farradox
Člen | 1
+
0
-

Ahoj, vůbec se mi nedaří předávat komponenty přes Multiplier šabloně.

protected function createComponentModules($name = "PageData") {
//obsah stejný jako v příspěvku "6.":
}

Zde je vše v pořádku. V Debugger Baru vidím vytvořenou komponentu „PageData“ přes Multiplier. Ovšem při volání komponenty v šabloně už se mi nedaří nic zobrazit.

{control modules-PageData}

„Maximum function nesting level of ‚100‘ reached, aborting!“

Netuší někdo v čem bych měl hledat chybu? Díky

Editoval farradox (12. 4. 2013 10:31)