Jak vytvářet komponenty až když jsou potřeba, (asi) bez továrničky?
- joe
- Člen | 313
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í Multiplier
u.
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á…
- joe
- Člen | 313
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.).
- duke
- Člen | 650
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
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
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
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
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
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
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)