Rozšíření ArrayAccess ve formulářích
- llook
- Člen | 407
Rád bych si rozšířil ArrayAccess u formulářů. Konkrétně metodu offsetGet, aby si pamatovala, ke kterým komponentám jsem už takto přistupoval a ke kterým ještě ne.
Jaký je důvod pro to, že jsou ty metody final?
Ještě nastíním, k čemu by mi to bylo dobré. Tohle udělátko na
formuláře je super v tom, že v raných fázích, kdy se ještě struktura
formuláře často mění, používám provizorně metodu render() a nové
fieldy tedy přidávám jenom na jednom místě. Jakmile si myslím, že mám
hotovo, tak si teprve vypiplám šablonu. Jenže myslet znamená… Potom někdy
formulář ještě dál rozšiřuju a pak by se mi hodila nějaká metoda
render komponenty,které jsem si ještě nevykreslil sám()
.
- paranoiq
- Člen | 392
myslím, že přesně kvůli takovýmhle nápadům je ta metoda final. arrayAccess má přesně definovanou funkčnost a jakékoliv ‚vedlejší efekty‘ jsou nežádoucí. neočekávané vedlejší efekty přispívají jen k horší čitelnosti kódu. měl bys to raději napsat víc ukecaně, zato ale přehledněji.
- David Grudl
- Nette Core | 8218
V podstatě je to tak, jak píše paranoiq. Existuje více funkcí pro přístup ke komponentám a kdyby jedna z nich měla vedlejší efekt, vedlo by to k těžko odhalitelným chybám.
Detekci vykreslení komponenty je potřeba vložit na místo, kam patří, tedy do metody getControl(). Takové rozšíření vidím jako užitečné a do knihovny ho rád přidám.
- llook
- Člen | 407
Tyhle problémy si uvědomuju. Metoda getControl() mě nenapadla, protože bez zásahů do kódu Nette bych si musel každou tu FormControl třídu podědit, do každé dát copy&paste rozšíření getControl() a pak si napsat svoje vlastní addNěco() metody, zatímco u offsetGet() bych rozšiřoval jenom jednu metodu…
Pokud tuhle funkčnost nějak přidáš přímo do Nette, tak to bude pro mě ideální.
- llook
- Člen | 407
Tak mě napadlo, že by vás mohlo zajímat, jak jsem to vyřešil provizorně. Je to jak říká paranoiq „víc ukecaně“, nebo jak říkám já, „repeat-yourself principle“:
<tr>
<td><?= $form["field1"]->label ?></td>
<td><?= $form["field1"]->control ?></td>
</tr>
<tr>
<td><?= $form["field2"]->label ?></td>
<td><?= $form["field2"]->control ?></td>
</tr>
<?php $form->renderContainerWithout("field1", "field2") ?>
Metoda renderContainerWithout() je jednoduchá extension method.
- David Grudl
- Nette Core | 8218
V nových formulářích mají všechny prvky příznak
$control->isRendered()
, který říká, zda byl nebo nebyl HTML
element vygenerovaný.
Ještě k metodě renderContainerWithout(): protože formuláře (nebo
vůbec komponenty) mohou tvořit složitější struktury, než prosté
jednorozměrné pole, je lepší je iterovat přes rekurzivní iterátor.
V akutální verzi jsem se to pokusil maximálně zjednodušit pomocí metody
ComponentContainer::getComponents()
(možná lepší pojmenování
by bylo ComponentContainer::getIterator()
, ale hapruje to s tímto
omezením PHP).
getComponents() má dva nepovinné parametry. První říká, zda se má iterovat do hloubky, a druhý filtruje vrácené prvky podle typu (tj. třídy nebo interface).
Metoda renderContainerWithout() by uvnitř mohla vypadat nějak takto:
foreach ($this->getComponents(TRUE, 'Nette\Forms\FormControl') as $control)
{
if (!$control->isRendered())) {
... vykreslime ...
}
}