Rozšíření ArrayAccess ve formulářích

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

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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 ...
    }
}