signál volá pouze defaultní render(): jak čistě vyrenderovat jen potřebný obsah?

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

Zdravím,
můj problém:

Mám komponentu s několika renderXX() metodami lišícími se tím, kde je obsah vykreslován. Pokaždé jde víceméně o totéž, jinak formátované, případně selectované s jinými parametry.

Kvůli interaktivitě používám hojně signály a tady narážím na problém: Nette při nich vyvolá pouze metodu render() a já pak jako reakci na signál nemohu invalidovat jen potřebný snippet, protože ten touto metodou není vykreslen, ale je součástí šablon pro renderXX().

Existuje jakýkoliv způsob, jak toto ČISTĚ vyřešit?
Já dnes ručně z render() vyvolávám všechny ostatní renderXX() a to je na nic (a poznámky s nadávkami na adresu Nette už mne neuspokojují :))
Používat deset samostatných komponent pro vykreslení 10× téměř totožného rovněž nechci.

mkoubik
Člen | 728
+
0
-

Momochodem: mít v komponentě víc render metod není úplně best practice. Radši bych si pro každé zobrazení vytvořil extra šablonu (za předpokladu že se ty view liší jen formátováním), přidal si setter $control->setViewName('viewName'); a všechno vykresloval pomocí render() (šablona "MyControl.$this->viewName.latte"). Případně si tu komponentu poďeď pro každé view (pokud se ty view liší i zobrazovanými daty) a název šablony si nastav do protected atributu.

A teď k tevému problému: signál by vůbec neměl volat žádnou render metodu, asi něco děláš špatně. V handle metodě je dobrým zvykem přesměrovat na stejné view ($this->redirect('this')) pokud se nejedná o ajaxový požadavek (v tom případě jen invaliduješ potřebné snippety). Každopádně {control foo:bar} by po překreslení mělo zavolat správnou render metodu.

Radši ukaž kód té komponenty a šablony ze které ji vykresluješ.

Editoval mkoubik (13. 2. 2014 12:26)

Felix
Nette Core | 1247
+
0
-

Tohle jsem take resil. V metode render ve ktere jsem nemel nic jineho nez:

public function render()
{
    if ($this->presenter->isAjax()) {

        if ($this->isControlInvalid('basket-lite-status')) {
            $this->renderLite();
        }

        if ($this->isControlInvalid('basket-list-order')) {
            $this->renderListOrder();
        }
    }
}
Prado
Člen | 21
+
0
-

mkoubik:
No pojem „best practice“ má pro mne asi jiný význam. Mně naopak dává maximální smysl nevytvářet deset komponent představující jiné pohledy na totéž, ale právě mít jen jednu a v ní deset metod renderxx(). Obzvláště, když stejná komponenta může být na stránce vykreslena vícekrát a pak není nutné duplikovat její vnitřní stavy (kolekce, entity atd).

Postup s jednou render(), která se rozvětví mezi různé šablony také používám, ale jen tam, kde nasettovaný stav komponenty ovlivňuje výběr šablony pro vykreslení. Předat výběr view jako stav komponenty se mi nelíbí z pohledu čistoty a taková obezlička se projevuje právě i na nemožnosti vykreslit na stránce komponentu (instanci) vícekrát v jiné podobě.

V handle metodě právě při ajaxu není jasné jaké snippety se mají po invalidaci vykreslit.

Ukázku zdrojáku zaslal Felix, ta tento příklad dobře popisuje: dva různé pohledy na košík a třeba tam bude jeden handler pro odmazání položky z košíku, přičemž komponenta normálně netuší, který renderXX() má vykreslit.

Felix:
Díky tohle zkusím, já tam právě doteď volal zbytečně všechny renderery. Takže pokud tohle bude fungovat i tam, kde se na stránce nepoužívají všechny renderery, je můj problém vyřešen.

Editoval Prado (13. 2. 2014 22:40)

Felix
Nette Core | 1247
+
0
-

Rikam si, jestli tohle je vubec bug a ne proste klasicke chovani. Jeslti ti to bude fungovat (jako me) tak se s tim da podle me zit.

Rikal jsem si, ze by to pak slo nejak potunit neco jako:

/**
 * @invalidate basket-list-order
 */
public function renderLite() {
}