Redirect z komponenty pomocí presenteru s použitím lazyloadingu

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

Zdravím,
potřebuji uvnitř komponenty provést redirect pomocí presenteru. Ovšem pokud je komponenta připojena k presenteru pomocí lazyloadingu (createComponentTestControl), redirect je volán již v době vykreslování (až z šablony se objekt inicializuje) a to je na redirect pozdě – objeví se tedy systémová AbortException.

Řešením je na komponentu „sáhnout“ předem. Tím však komponenta dost ztrácí na hodnotě pokud v jejím popisu bude: „Nesmíte jí inicializovat lazy“.

Příklad:

class TestControl extends \Nette\Application\UI\Control {

        public function attached($presenter) {
            parent::attached($presenter);

            if($presenter instanceof Nette\Application\UI\Presenter){
                $this->presenter->redirect("Sign:in"); // při lazyloadingu vyvolá AbortException
            }
        }
}

Ptám se tedy, přehlédl jsem nějakou možnost a tudíž existuje nějaké řešení v dosavadním Nette? Popřípadě existuje vůbec nějaký workaround, který by měla v režiji již komponenta? Pokud ne, nestálo by za to upravit v Nette něco aby tohle fungovalo?

enumag
Člen | 2118
+
0
-

Myslím že tahle přesměrování by měl řešit presenter.

Casper
Člen | 253
+
0
-

Myslím že tahle přesměrování by měl řešit presenter.

Obecně je to rozhodně lepší, upřesním tedy o co jde:

Dělám komponentu StepWizard (StepForm) a mám v session aktuální step, který je duplikovaný v URL (parametr presenteru, aby se na kroky dalo odkazovat). Pokud mi ale někdo podstrčí neplatný step, chci se přesměrovat na nějaký správný (a nepovažuji za správné nechat v URL špatný step a jen vykreslit správný).

Momentálně problém řeším tak, že vyhodím flashMessage o neplatném kroku a formulář vůbec nezobrazím. Zajímalo mne však, zda existuje lepší řešení (kromě přenášení aktuálních stepů pomocí signálů, což mi nepřijde vhodné – minimálně je dost nepořádku v url).

Editoval Casper (28. 11. 2012 15:39)

bazo
Člen | 619
+
0
-

co takto vytvorit komponente udalost onInvalidStepRequested a v presenteri nan navesit presmerovanie?

Casper
Člen | 253
+
0
-

co takto vytvorit komponente udalost onInvalidStepRequested a v presenteri nan navesit presmerovanie?

Tím by komponenta neřešila vlastní problém a jen jej delegovala výše. Pravděpodobně by to šlo, ale osobně mi přijde lepší řešení pomocí flashMessage. Nicméně díky za hint.

pepakriz
Člen | 246
+
0
-

Napadají mě dvě řešení.

Workaround 1: šáhnout na komponentu těsně před vykreslením.

public function beforeRender()
{
    parent::beforeRender();
    $this['testControl'];
}

Workaround 2: obalit šablonu makrem {capture}, čímž se stránka nebude posílat na výstup a přesměrování bude fungovat. Má to samozřejmě nevýhodu v pozdrženém odesílání dat.

vvoody
Člen | 910
+
0
-

Keď chceš mať plnú kontrolu nad tým, s ktorím stepom môže užívateľ pracovať, prečo potom používaš parameter v url? Je tam úplne k ničomu, keď tomu parametru ani nedôveruješ.

Casper
Člen | 253
+
0
-

Napadají mě dvě řešení.

díky za nápady

Keď chceš mať plnú kontrolu nad tým, s ktorím stepom môže užívateľ pracovať, prečo potom používaš
parameter v url? Je tam úplne k ničomu, keď tomu parametru ani nedôveruješ.

Parametr z url může být platný pokud už na daném kroku uživatel formulář vyplnil. Není platný, pokud je to „budoucí“ krok.

vvoody
Člen | 910
+
0
-

To mi je jasné, ale odpoveď na moju otázku to nieje. Ovládanie toho, ktorý step sa vykreslí, môže závisieť len od hodnoty v session, ktorú budeš meniť signálmi. Tie sa spracúvajú vždy pred rendrovaním, takže môžeš bez problému redirectnúť, keď bude v signálne nesprávna hodnota.

Ak je parameter v url aj tak vyžadovaný, tak by som tvoju komponentu zabalil do služby, ktorá by mala dve metódy. Prvá metóda by v beforeRender alebo skorej v action validovala parametru z url a prípadne zavolala redirect. A druhá metódo by v továrničke vytvorila a vrátila komponentu. Takže ak bude v url nesprávny step tak sa komponenta nebude nadarmo inštancovať a pripájať k presenteru.

Aearsis
Člen | 57
+
0
-

Nikdo to tu nezmínil – AbortException je vyjjímka signalizující ukončení běhu aktuálního presenteru. Je to proto, aby volání přesměrování vybublalo až k aplikaci. To, že vyskočí při zavolání redirectu je tedy naprosto v pořádku, application jí odchytí a přesměruje podle RedirectResponse presenteru.

Editoval Aearsis (30. 11. 2012 21:22)

Casper
Člen | 253
+
0
-

Ovládanie toho, ktorý step sa vykreslí, môže závisieť len od hodnoty v session, ktorú budeš meniť signálmi

Pokud to chápu dobře, nechával bys trvale v URL poslední volaný signál?

  • Pokud ano, pak je to řešení zmíněné již v mém prvním příspěvku, které se mi nezdá vhodné (minimálně je to nezapamtovatelné, viz ?myStepForm-step=product&do=myStepForm-setStep).
  • Pokud ne (tedy došlo by k validaci kroku, uložení do session a přesměrování na this), pak je chování nepřjatelné, protože by všechny kroky měli stejné URL a uživatel by mezi nimi nemohl přecházet browser tlačítky zpět a vpřed.
  • Odpověď na tvou původní otázku by tedy pravděpodobně měla znít takto: parametr v URL potřebuji především kvůli odlišení jednotlivých kroků a možnosti přecházet mezi nimi pomocí zpět / vpřed.

To, že vyskočí při zavolání redirectu je tedy naprosto v pořádku, application jí odchytí a přesměruje podle RedirectResponse presenteru.

Pokud již AbortException vyskočí v Laděnce, tak již nebyla odchycena application a naprosto v pořádku to tedy rozhodně není, protože přesměrováváš v době, kdy už k přesměrování dojít nesmí (typicky v render metodě).

enumag
Člen | 2118
+
0
-

Zkusím také něco navrhnout.

  1. Signály bych v tomto případě nevyužil.
  2. Každý krok je závislý na tom předchozím, tedy uživatel se sice může vrátit na libovolný již provedený krok, ale pokud tam něco změní, je nutné aby všechny následující kroky provedl znovu. (Případně by se daly defiunovat složitější závislosti, ale to je už jiné téma.) ⇒ V session bych ukládal číslo kroku, na který se uživatel může dostat (tj. prošel všechny předchozí pěkně po pořádku).
  3. V persistentním parametru bych ukládal krok, na který se uživatel právě dívá – což se může lišit od toho co mám v session!

Pokud jde o přesměrování, to by dle mého názoru komponenta neměla řešit přímo. Místo toho bych nabídnul metodu isStepValid() a nechal bych toho kdo komponentu chce použít aby si tento stav ošetřil. Pokud by to neošetřil tak místo formuláře vypsat hlášku a odkaz na poslední validní krok.

Ošetření chybného kroku by tedy programátor používající komponentu mohl provést dle svého pokud mu výchozí chování nevyhovuje. Komponenta by též měla mít metodu getLastValidStep(). Klíčové je, že to případné vlastní ošetření bude typicky provádět v beforeRender(), tedy dříve než je něco posláno na výstup. Aby se vůbec bylo možné zavolat isStepValid(), musí komponenta být už vytvořená. Může v klidu zavolat redirect s tím parametren getLastValidStep().