Vylepšené chování snippetů po 14 letech

David Grudl
Nette Core | 8218
+
+8
-

Snippety v Nette fungují v podstatě v nezměněné podobě svého vzniku někdy před 14 lety. Nejspíš asi vcelku dobře, protože si neuvědomuju, že by byly nějaké otevřené issues. Neočekávané chování, na které lidi nejvíc narážejí, je, že při překreslování se neposílají parametry do {control foo $arg, ...} (ani nelze změnit metodu {$control foo:bar}). Je to proto, že se vlastně vůbec nevykresluje šablona, která {control} obsahuje, ale rovnou se kreslí komponenta voláním její metody render().

Říkal jsem si, že by se to mohl problém s parametry dát řešit pomocí snippetArea:

{snippetArea fooArea}
	{control foo $arg, ...}
{/snippetArea}

A pak by stačilo jen invalidovat areu $this->redrawControl('fooArea').

Zkusil jsem to doplnit do nette/application v3.1-dev. Ale upřímně, fungování snippetů už dávno nemám v hlavě, takže absolutně netuším, jestli to něco nerozbilo. Budu proto rád, když to vyzkoušíte a dáte mi zpětnou vazbu.

Funguje to teď tak, že pokud se komponenta nepřekreslí přes šablonu, vyvolá se standardní automatické kreslení přes metodu render().

m.brecher
Generous Backer | 863
+
0
-

Ahoj,

nainstaloval jsem si latte/latte dev-master #bdb3 (v3.1-dev nešlo, instaloval jsem v3.0.x-dev) a mám tyto první poznatky:

zkouším co mě aktuálně pálí – ajaxový submit formuláře, kde se předává parametr do {control …}.

Latte:

{snippetArea 'myFormWrapper'}
	{control 'myForm' $heading = 'Editační formulář'}
{/snippetArea}

Překreslení spouštím tak, že komponenta v události submit formuláře volá presenter, aby překreslil snippetarea v hlavní šabloně

$control->form->onSubmit[] = fn() =>  $control->presenter->redrawControl('myFormWrapper');

kde $control je komponenta UI\Control v níž je zabalený Form.

Formulář mám složitější, ale to podstatné je zde:

class MyForm extends UI\Control
{
    #[Persistent]
    public int  $num = 0;

    protected function createComponentForm(): BaseForm
    {
        $form = new BaseForm;

        if($form->submitter === '__addItemRow'){  // $submitter mám vyřešený v BaseForm
            $this->num ++;
        }

		/ ...

		$form->addSubmit('__update', 'Uložit změny')
           ->onClick[] = $this->handleUpdate(...);

		$form->addSubmit('__addItemRow', 'Přidat položku')
           ->setValidationScope([]);

        //....

        return $form;
    }
}

testy

Submit ‚Uložit změny‘

  • submit funguje, formulář se překreslí, parametr $heading se přenese SPRÁVNĚ.
  • uvnitř šablony myForm.latte (univerzální šablona formulářů) mám {include ‚flashBox.latte‘}, který se NEVYKRESLÍ

Submit ‚Přidat položku‘

  • submit funguje, formulář se překreslí, persistentní parametr $num se do <form action=„…“ ..> NEVYKRESLÍ

náměty na úvahu nad případným řešením

Pokud jsou komponenty SPRÁVNĚ navrženy a požadovaná funkce rozložena do malých, izolovaných komponent, pak si myslím, že neměla vznikat potřeba přenášet v šablonách parametry z parenta na potomka. Kdyby šablona formuláře, který překresluji, byla pro jeden konkrétní formulář, umístil bych text, který přenáším parametrem ‚Editační formulář‘ přímo do šablony formuláře.

Jenže já chci mít jednu obecnou šablonu pro běžné formuláře, kterých je 90% a do obecné šablony konkrétní text zapsat nejde. Text pro konkrétní formulář tedy zapíšu do šablony akce presenteru jako parametr předaný do {control ‚myForm‘}, což je nejlepší řešení – minimalistické a přehledné.

Jiné použití, kdy se hodí předat parametr do šablony komponenty je nějaká frontendová konfigurace komponenty, kdy potřebuji ovlivnit samotné vykreslení komponenty (např. navigační menu zabaleno/rozbaleno, …).

V případech, kdy předání parametru do {control} komponenty dává smysl se nejedná o závislost mezi šablonami nebo komponentami. Jde o zápis textu, který by měl být v šabloně komponenty, ale protože je obecná, zapisuje se do {control}. Nebo o předání true/false/int statické hodnoty, nikoliv proměnné v případě konfigurace komponenty.

Tak si myslím, že by možná stačilo, kdyby Latte při kompilaci hlavní šablony „překopírovalo“ staticky zadané parametry v {control} do zkompilované šablony komponenty. Při vykreslování šablony komponenty by se při standardním requestu použily parametry z hlavní šablony, při ajaxovém redraw celé komponenty by se použily předem „přenesené“ parametry a hlavní šablona by se nemusela vůbec volat. Což by tak mělo být – komponenty by měly být nezávislé.

Samozřejmě je otázka, jak moc by to bylo složité a jestli se to vyplatí. Statické texty můžeme snadno vložit do šablony komponenty i v metodě render(), což nám komponentu znepřehlední, ale problém to řeší.

mystik
Člen | 308
+
+2
-

Tam je zakladni problem v tom ze jedna komponenta se muze renderovat v ramci parent sablony nekolikrat s ruznymi parametry v {control}. Jak pak poznat kterou verzi prekreslit kdyz se invaliduje jen snippet uvnitr komponenty? Musely by se pamatovat vsechny vyskyty a jejich parametry.