Refresh dat v komponente, ktera jsou predavana z presenteru

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

Zdravím, řeším ajax po odeslání formuláře, kde bych chtěl aby se mi refreshnuli data v komponentě. Formulář odesílá data do databáze(to už funguje), a snad jsem správně nastavil i invalidaci komponenty, ale ta se neobnoví. Problém může být, že data do komponenty předávám z presenteru při jejím vytváření (potřebuji volat stejnou komponentu s různými daty). Existuje na to nějaké řešení?

Vytváření komponenty v presenteru:

<?php

protected function createComponentProjectList() {
        if ($this->user->isInRole('0')) {
            $control = new showProjectList($this->projektyRepository->findAllProjectsByView($this->user->id), $this->ukolyRepository->findAllTasksByView($this->user->id),$this->projektyRepository);
        } else {
            $control = new showProjectList($this->projektyRepository->findAllProjects(), $this->ukolyRepository->findAllTasks(),$this->projektyRepository);
        }
        return $control;
    }

?>

Zde je kód zpracovávající formulář po odeslání (kód proběhne, data jsou po refreshi v komponentě správně), ale nepovede se invalidace.

<?php
public function createNewProjectSubmitForm(Form $form) {
        if(!$this->isAjax()){
            $id = $this->projektyRepository->newProject($form->getValues());
            $this->redirect('Projects:projectDetail', $id);
        }else{

            $id = $this->projektyRepository->newProject($form->getValues());
            $this->getComponent('projectList')->invalidateControl();
        }

    }

?>
Felix
Nette Core | 1196
+
0
-

Mozna bych tu logiku presunul do komponenty a pak v sablone mel treba,

{control projectList, id => $id}

Zkus trochu vic popsat jak ji chces pouzit.

Muhahe
Člen | 79
+
0
-

Nějak jsem nepochopil co jsi myslel tím předat logiku do komponenty, ale zkusím popsat moji myšlenku.

Komponenta reprezentuje tabulku obsahující údaje z databáze. Pomocí jquery UI dialog vykresluji formulář pro přidání údajů do databáze přez AJAX. Po přídání bych rád, aby se komponenta překreslila s aktuálními udaji.

Komponentu vykresluji na různých místech a data která se mají vykreslit určuji v presenteru. Ten sáhne do modelu, vybere data a předá je parametrem komponentě. A zde si právě nejsem jist, jestli při pokusu o invalidaci a překreslení komponenty se mi i znovu přečtou data z databáze.

Felix napsal(a):

Mozna bych tu logiku presunul do komponenty a pak v sablone mel treba,

{control projectList, id => $id}

Zkus trochu vic popsat jak ji chces pouzit.

Muhahe
Člen | 79
+
0
-

Jeste me napadlo jestli mam ubec spravnou myslenku a jestli je to mozne.

Prezenterem na dane strance vykresluji pouze komponentu (nazveme ji A) a komponentu na vykresleni formulare pro pridani projektu (nazveme ji B).

latte sablona stranky

{block content}
<div>
<h1>Projects</h1>
   {control projectList}

<div id="newProjectFormContainer">
{control newProjectForm}
</div>
<div id="newTaskFormContainer">
{control newTaskForm}
</div>
</div>
{/block}

Komponenta formulare je skryta a zobrazuje se az po kliknuti tlacitka pomocí jquery dialog.

Po vyplneni a odeslani formulare je volana metoda presenteru createNewProjectSubmitForm, ktera by mela pridat projekt do databáze a invalidovat komponentu A (překreslit a zobrazit přidaný projekt). Metoda createNewProjectSubmitForm se nachazi v presenteru.

<?php
public function createNewProjectSubmitForm(Form $form) {
        if (!$this->isAjax()) {
            $id = $this->projektyRepository->newProject($form->getValues());
            $this->redirect('Projects:projectDetail', $id);
        } else {

            $id = $this->projektyRepository->newProject($form->getValues());
            $this->invalidateControl('projectList');
            $this->getComponent('projectList')->invalidateControl();

        }
    }
?>

Projekt se do databaze prida spravne, avsak nejsem schopen zprovoznit invalidaci komponenty.

Komponenta A je volana v presenteru a jsou ji predany data, ktera se maji zobrazit.

Zkousel jsem i funkcnost samotne invalidace tak, ze v komponente vypisuji aktualni cas kdy byla komponenta vykreselena (v pripade ze by se nepredali data), ale cas se neaktualizuje. Z cehoz odvozuji ze ani komponenta se neinvaliduje.

Je ubec mozne aby tento princip fungoval? Pokud by byl nekdo ochotny pomoci, velice rad poskytnu pripadne dodatecne info, ale nenapada me co vice dal bych mel uvest.

Za jakoukoli pomoc budu velice rad.

Editoval Muhahe (26. 12. 2013 11:10)

Jan Suchánek
Člen | 404
+
0
-

@Muhehe: Predat do komponenty je mysleno tak, aby komponenta dostala model a parametry, model prez neon. Celou logiku delegovat na komponentu a tim odlehcit spagety v presenteru?

Muhahe
Člen | 79
+
0
-

jenicek napsal(a):

@Muhehe: Predat do komponenty je mysleno tak, aby komponenta dostala model a parametry, model prez neon. Celou logiku delegovat na komponentu a tim odlehcit spagety v presenteru?

Momentalne vytvarim komponentu A takto

<?php
protected function createComponentProjectList() {
        if ($this->user->isInRole('0')) {
            $control = new showProjectList($this->projektyRepository->findAllProjectsByView($this->user->id), $this->ukolyRepository->findAllTasksByView($this->user->id), $this->projektyRepository);
        } else {
            $control = new showProjectList($this->projektyRepository->findAllProjects(), $this->ukolyRepository->findAllTasks(), $this->projektyRepository);
        }
        return $control;
    }
?>

Mam to z toho duvodu, ze konponentu potrebuji volat z vice mist s ruznymi daty.

Pokud dobre chapu tvuj navrh, mel bych logiku, ktera urcuje jaka data budou zobrazena presunout do komponenty?

A nebo predavat referenci na model primo komponente?

<?php
...
 $control = new showProjectList("predat model", "parametr vyberu")
...
?>

Nebo jeste treti moznost me napada z toho co sem tu cetl, tak zaregistrovat model komponente v souboru .neon?

Bohuzel se ptam jako prumerny primat, ale jsem z toho trochu zmaten. Jeste me napada, neni zde na to v ukazkach, nebo planette nejaka ukazka? Snazil jsem se neco najit ale neuspesne tak jestli mi neco neuniklo.

Pokud by slo o druhou moznost, porad me zarazi ze se neinvaliduje alespon ten cas.

Jan Suchánek
Člen | 404
+
0
-

@Muhahe: Mit komponentu v configu a tam ji predat modely a na parametry setry v presentreru?

Šaman
Člen | 2659
+
0
-

Vytvořil jsem Gist s ukázkou komponenty, která si injectuje závislosti pomocí autowiringu přímo v configu.

Ukázka by se dala ještě zjednodušit, tohle jsem vykopíroval z jednoho ukázkového projektu. Idea je taková, že kromě komponenty si vytvoříš tovární třídu (servisu), která dostane všechny závislosti v configu jako jakákoliv jiná servisa a ty si ji injectneš do presenteru a pomocí ní vytváříš konkrétní instance dané komponenty.
Ty traity jsou jenom kvůli zjednodušenému injectování, s problematikou továrny nijak nesouvisí.

Jestli ti tohle bude jasné, tak si ještě zkus vyhledat něco o generovaných továrničkách – aplikace se ti pak ještě maličko zmenší, protože část kódu si Nette vygeneruje samo. V Nette 2.1@dev pro to byla sekce factories, dnes se to prý změnilo, tak ukázku neposílám. V principu to je však totéž, jen není potřeba psát celou tovární třídu, ale jen její rozhraní.


Dodatek: @Jenicek: Není dobré vytvářet přímo komponentu v configu, protože komponent můžeš mít na stránce několik a v configu můžeš vytvářet jen servisy (tedy konkrétní instance, které se předávají v celé aplikaci). Proto si v configu vytvoříš jen továrnu (služba, stále jen jedna), která na požádání vytvoří libovolný počet konkrétních komponent.

Editoval Šaman (26. 12. 2013 13:46)

Jan Suchánek
Člen | 404
+
0
-

@Muhahe: Napsal bych priklad, ale pisu z mobilu a neni to moc user friendly.

Muhahe
Člen | 79
+
0
-

Diky moc oba, urcite ozkousim co to pujde.

@Jenicek: To chapu, nechci nikoho moc zdrzovat svejma problemama. Slo mi hlavne o postrceni ale diky za ochotu

Muhahe
Člen | 79
+
0
-

Jeste me napadlo, ciste z edukativnich duvodu, ty mnou vyse uvedene zpusoby nejsou mozne?
Pripadne proc? Protoze komponenta je s parametrem?
Dale jsem v ukazkach nasel navody na jednoduchou invalidaci, ktera se pouzivala tak jak jsem to zkousel.
Precetl jsem snad kompletni sekci dokumentace, ale zustava mi dost otazek. Nerad bych prudil, jen mne to porad vrta hlavou.

Jan Suchánek
Člen | 404
+
0
-

@Muhahe: Šamanovo řešení je čistší, napr me vadilo dvakrat new toho sameho konkretne showProjectList, ale pokud je to pro tebe ok?

Muhahe
Člen | 79
+
0
-

jenicek napsal(a):

@Muhahe: Šamanovo řešení je čistší, napr me vadilo dvakrat new toho sameho konkretne showProjectList, ale pokud je to pro tebe ok?

To samozrejme mas pravdu, to dvakrat new nebylo moc uzasny, ale momentalne mi jde spis o vysledny princip, proc ta invalidace nefungovala. Jde mi spise o celkovy vysledek nez o uhlazenost kodu. Te jsem se chtel venovat pote az bude funkcnost ± hotova.

Postupoval jsem myslenkove asi tak: vedel jsem co chci → nasel jsem jak to udelat → zkusil jsem to naprasit, abych overil jestli to funguje spravne (zde jsem se zasekl) → dal bych do pucu kod

A prave k tomu poslednimu bodu uz jsem se nedostal :/

Editoval Muhahe (26. 12. 2013 17:33)

Jan Suchánek
Člen | 404
+
0
-

@Muhahe: neni invalidateControl depricated? Co ti vraci firebug pri ajaxu?

Muhahe
Člen | 79
+
0
-

jenicek napsal(a):

@Muhahe: neni invalidateControl depricated? Co ti vraci firebug pri ajaxu?

Problem je, ze ani firebug, ani chrome, ani IE konzole nevyhodi zadnou chybu. Pozadavek ajaxu je 200 OK, data se pridaji a kdyz refreshnu stranku tak je vse tak jak ma byt. Jedine co neprobehne, tak je prave ta invalidace komponenty, ktera by to refreshnuti mela zaridit (pokud jsem vse spravne pochopil).

Jestli je deprecated, tak to nevim nikde jsem to nenasel.

Kdybych tam mel chybove hlasky tak bych s tim neotravoval, ale tohleto me prave dostava do kouta. Dokonce nette log je taky prazdnej.

Proste z nejakeho duvodu invalidace neprobehne a nejsem schopen dat dohromady proc.

Editoval Muhahe (26. 12. 2013 20:23)

Jan Suchánek
Člen | 404
+
0
-

http://bit.ly/1c9a8ZE zkus mrknout

Muhahe
Člen | 79
+
0
-

jenicek napsal(a):

http://bit.ly/1c9a8ZE zkus mrknout

Koukam na to, ale jedna se teprve o testovaci verzi ne? Pouzivam 2.0.8 a predpokladal jsem ze by tam melo ± vse fungovat.

Zkusim jsem preskocit na novou verzi nette a redrawControl() je stejny problem. Polozka se prida, ale komponenta se neprekresli chybova hlaska neni ani v chrome, firebugu, IE konzoli, nette logs.

Editoval Muhahe (26. 12. 2013 21:37)

jiri.pudil
Nette Blogger | 1029
+
0
-

Dvě otázky:

  1. Ve Firebugu i v Chrome Dev Tools se můžeš podívat na obsah, který ti ten ajaxový požadavek vrátil. Je v něm to, co očekáváš (tzn. položka „snippets“ obsahující aktualizovaná data)?
  2. Co vlastně používáš pro ajaxizaci na straně klienta? nette.ajax.js?
Muhahe
Člen | 79
+
0
-

jiri.pudil napsal(a):

Dvě otázky:

  1. Ve Firebugu i v Chrome Dev Tools se můžeš podívat na obsah, který ti ten ajaxový požadavek vrátil. Je v něm to, co očekáváš (tzn. položka „snippets“ obsahující aktualizovaná data)?
  2. Co vlastně používáš pro ajaxizaci na straně klienta? nette.ajax.js?

Ve firebugu->Konzole->All->odezva vraci prazdne pole state (nebo JSON).

Na strane klienta pouzivam nette.ajax.js verze 1.2.2 stazene primo ze stranek Nette.

A prave co se tyce bodu 1) tak tam prave tusim ze bude problem, ze se invalidace/prekresleni neprovede ale nedokazu prijit nato proc. Snazil jsem se vse jed dle navodu.

Editoval Muhahe (26. 12. 2013 22:30)

Jan Suchánek
Člen | 404
+
0
-

A mas spravne vse obalene snipetama v latte? A kdyz se ti vraci payload co konkretne vrati? Nic?

Jan Suchánek
Člen | 404
+
0
-

@Šaman: komponentu vytvarim pomoci interface, lze jednim interfacem vyrabet vic ruznych komponent nebo jen vic stejnych komponent. Myslim posledni plati ne?

Šaman
Člen | 2659
+
0
-

@jenicek: Pošli nějakou ukázku, nevím co myslíš tím interface. JEstli generované továrny, tak to je v pohodě. Ale tím v kontejneru nevytváříš tu komponentu, ale tovární třídu (generovanou), která pak v konkrétních továrničkách presenteru (metoda createComponentXxx) vytváří konkrétní instance.

Jan Suchánek
Člen | 404
+
0
-

@Šaman: tak to provadime stejne. V createComponentXxx je napr. $control = $this->example->create() a dosetuju a vratim jako vysledek. Jen sem se ptal, zda jednou takovou tovarnou mohu vracet i jinou komponentu nebo je to vazane na jedinou?

Šaman
Člen | 2659
+
0
-

Jestli si nepíšeš vlastní tovární třídu (jak to mám v ukázce) a využíváš generované továrny, tak při každém zavolání metody create() dostaneš novou unikátní instanci komponenty (ta metoda create v sobě obsahuje vytváření pomocí new).

Pokud si píšeš vlastní, tak záleží na tom, jak si to napíšeš. Ale od metody create bych vždy očekával vytvoření nové instance.

Takže odpověď je, že můžeš vytvářet kolik chceš nezávislých komponent.

Editoval Šaman (27. 12. 2013 10:30)

Jan Suchánek
Člen | 404
+
0
-

@Šaman: ok, vlastni jsem nepouzival Ten trait je zajimavej.

Muhahe
Člen | 79
+
0
-

jenicek napsal(a):

A mas spravne vse obalene snipetama v latte? A kdyz se ti vraci payload co konkretne vrati? Nic?

Hmm tak ted si nejsem jistej jeslti jsem postupoval spravne, ale mel sem zato ze pokud chci invalidovat komponentu, pak nemusi byt obalena snipettem, nekde jsem to cetl pokusim se znovu najit.

A ted asi trochu blba otazka, ale payload neni v firebugu zalozka odpoved? Pripadne kde payload zistim?

Jan Suchánek
Člen | 404
+
0
-

@Muhahe: Ze by nemela byt obalena snipetem to si nemyslim. Kde si na to prisel?

Muhahe
Člen | 79
+
0
-

jenicek napsal(a):

@Muhahe: Ze by nemela byt obalena snipetem to si nemyslim. Kde si na to prisel?

Nojo tak sem trotl. Se snipetem uz to konecne hazi chybovou hlasku :) diky moc mam se kam hnout