Component with name ‚XXX‘ does not exist
- reflex
- Člen | 28
Zdravim,
ladenka hlasi chybu ‚Component with name 'MetaForm‘ does not exist.' pritom vse bych mel mit spravne.
tovarnicka:
<?php
function createComponentMetaForm()
{
$form = new AppForm($this, 'meta_form');
$form->addText('name', 'Název')
->addRule(Form::FILLED, 'Vyplňte název!');
$form->addSubmit('save', 'Uložit');
$form->onSubmit[] = array($this, 'add');
return $form;
}
?>
v sablone:
{control MetaForm}
Ja uz z toho pomalu zacinam sedivet, nekdo radu? :]
Editoval reflex (14. 12. 2009 18:32)
- Ondřej Brejla
- Člen | 746
Co třeba takto?
public function createComponentMetaForm($name) {
$form = new AppForm($this, $name);
$form->addText(‚name‘, ‚Název‘)->addRule(Form::FILLED, ‚Vyplňte název!‘);
$form->addSubmit(‚save‘, ‚Uložit‘);
$form->onSubmit[] = array($this, ‚add‘);
}
a
{control metaForm}
- Ondřej Brejla
- Člen | 746
Pokud cpeš název už do konstruktoru, tak vždy radši z továrničky (jak jsem psal). To co sodae popisuje sice funguje, ale nemělo by se to radši používat. Nejhezčí je stejně verze s returnem :-)
- Panda
- Člen | 569
Koukám, že tu jsou menší nesrovnalosti kolem továrniček…
Jak již bylo naznačeno, u názvů komponent se rozlišuje velikost písmen. Pokud nechám komponentu připojit k presenteru automaticky (viz dále), je první písmeno vždy malé.
Další věc je připojení komponenty presenteru. V podstatě mám 2 možnosti, jak to udělat: ručně a automaticky. Ruční metoda znamená, že komponentě v konstruktoru uvedu jejího rodiče a její název – v takovém případě se komponenta k presenteru připojí ihned při vytvoření. Pokud se rozhodnu pro automatickou metodu, tak konstruktor zavolám bez těchto parametrů a pak objekt s komponentou vrátím. Presenter pak zkoumá, jestli navrácená komponenta již je připojená, nebo není. Pokud není, tak jí připojí pod příslušným názvem (první písmenko malé!) k presenteru.
Pokud bych to měl shrnout:
O připojení se starám sám – uvedu rodiče a název komponenty
v konstruktoru a továrnička nemusí vracet nic. Příklad:
public function createComponentMetaForm($name) {
$form = new AppForm($this, $name);
// ...
}
O připojení se stará presenter (či jiný nadřazený kontejner) – rodiče ani název neuvedu a továrnička pak nově vytvořený objekt musí vrátit. Příklad:
public function createComponentMetaForm() {
$form = new AppForm();
// ...
return $form;
}
// Úprava: na podnět hosiplana jsem se po pár měsících podíval na
mechanismus vytváření komponent v aktuální verzi Nette a přibylo v něm
pár kontrol, takže je to trochu jinak, než jsem původně psal. Pokud
vyžádám komponentu MetaForm
(velké písmenko na začátku), tak
se žádná továrnička nevolá.
Jinak samotná tvorba komponent pomocí továrniček je velmi
zajímavá. Podívejme se například na to, co se stalo v kódu, který
způsoboval počáteční chybu…
Začněme makrem {control MetaForm}
. Presenter je
požádán o komponentu MetaForm
. Nejdříve se podívá, jestli
už neexistuje. Pokud opravdu neexistuje, tak přejde k procesu jejího
vytvoření pomocí továrniček. Nejdříve se podívá po nějaké
vhodné – najde createComponentMetaForm
(!), protože u názvů
funkcí v PHP nezáleží na velikosti písmen. V této továrničce se
vytvoří komponenta a připojí se k presenteru pod názvem
meta_form
a továrnička tuto komponentu vrátí. Protože už
továrnička již připojená je, tak se znovu nepřipojuje. Poté zkusí
presenter vrátit komponentu MetaForm
– ta ale neexistuje,
protože továrna vytvořila komponentu meta_form
.
Pokud bychom ale zavolali v šabloně {control meta_form}
,
tak aplikace skončí se stejnou chybovou hláškou – tentokrát se nenajde
továrnička, protože se hledá funkce s názvem
createComponentmeta_form
.
Pokud změníme první řádek továrny na
$form = new AppForm();
a necháme návratovou hodnotu, tak se
o její připojení postará presenter. Ale ten jí připojí pod jménem
metaForm
, takže máme opět stejnou chybovou hlášku –
komponenta s názvem MetaForm
neexistuje.
Pokud bychom zmíněný řádek upravili na
$form = new AppForm($this, 'MetaForm');
, tak by vše mělo
fungovat – komponentu s požadovaným názvem jsme si
připojili sami.
Doufám, že můj příspěvek je srozumitelný a že alespoň někomu
pomůže si záležitosti kolem továrniček v hlavě trochu urovnat.
Editoval Panda (14. 12. 2009 19:39)
- romansklenar
- Člen | 655
Pokud máte někdo čas, aktualizujte to v dokumentaci, dotazů tohoto typu je tu poslední dobou hodně. Je třeba ale proklikat celou dokumentaci, protože těch stránek kde jsou popsané komponenty je více
- reflex
- Člen | 28
Dekuji vsem, jeste bych doplnil co jsem vyzjistil
V tomto pripade muzu pouzit isSubmitted v ramci komponenty
<?php
function createComponentMetaForm($name)
{
$form = new AppForm($this, $name);
if (!$form->isSubmitted()) {
// nastaveni defaultnich hodnot
}
?>
V tomto pripade to zarve ‚Form is not anchored and therefore can not determine whether it was submitted.‘
<?php
function createComponentMetaForm($name)
{
$form = new AppForm();
if (!$form->isSubmitted()) {
// nastaveni defaultnich hodnot
}
?>
Tedy prvni varianta je asi ta „lepsi“
- Panda
- Člen | 569
Tak teď jsme se trochu nepochopili… Tím „kdykoliv“ jsem myslel i za
situace, kdy je formulář odeslán, tzn. ta kontrola na
isSubmitted()
je zde zbytečná:
<?php
function createComponentMetaForm()
{
$form = new AppForm();
// nastaveni defaultnich hodnot
return $form;
}
?>
Co se nastavování hodnot týče, tak by dle mého soudu mělo být v tom
místě, kde načítáš data z databáze. A to je většinou v
render<view>()
. Jinak je to ale asi celkem jedno, pokud to
člověk bude dodržovat všude.
Ale to už jde trochu mimo téma…
- Patrik Votoček
- Člen | 2221
Takže která z variant:
public function createComponentFooForm($name)
{
$form = new \Nette\Application\AppForm($this, $name);
//...
}
// nebo/vs.
public function createComponentFooForm()
{
$form = new \Nette\Application\AppForm();
//...
return $form;
}
Se dá považovat za best practice?