Problémy s AJAX vs. komponenta

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

Dobrý den,
mám následující problém:
Hlavní presenter – HomepagePresenter.php
v něm továrnička na komponentu:

<?php
...
    protected function createComponentContent()
    {
        $content = new Content($this->getAction(), $this->getName());
        $content->invalidateControl();
        return $content;
    }
...
?>

v příslušné šabloně (její jméno je se zavináčem)která se vykresluje:

...
        <tr>
            <td id="content">@{control content}</td>
        </tr>
...

Zdroják komponenty:

<?php
	class Content extends Control
	{
        protected $presenter;
        protected $view;

        public function __construct($presenter = null, $view = null)
        {
            $this->presenter = $presenter;
            $this->view = $view;
        }

		public function render()
		{
            Debug::dump(array($this->presenter, $this->view));
            $this->template->test = rand();
            $this->template->setFile(dirname(__FILE__) . '/content.phtml');
            $this->template->render();

		}

        public function handleTest($param)
        {
            Debug::dump($param);
            $this->invalidateControl();
            Debug::dump('bagr');
            $this->template->robots = 'noindex,noarchive';
        }
	}
?>

šablona:

{block #content}
    {snippet}
        {$test}
    {/snippet}
{/block}

handleTest se volá následujícím odkazem:

...
{foreach $menu as $key => $value}
<a href="{link content:test!, $value['view']}" class="ajax">{$key}</a>
{/foreach}
...

js zdrojáky jQuery používám z příkladu z automatu na kávu, rovněž i css styly.

Co dělám zle jestliže se šňupetová část stránky nikdy nepřekreslí a přitom ve firebugu to vrací odpověď, správný html kód, ale jen se mi nevykreslí tam kam má, nevykreslí se nikam. Zkoušel jsem šňupet pojmenovat, nepomohlo. Na co je pojmenování šňupetu? kde se to dá použít? Děkuji za pomoc, je to trochu akutní…

JakubKohout
Člen | 92
+
0
-

jenom sem to projel očima, ale chyba je pravděpodobně v tom že si přepsal metodu __construct Controlu ;) … blbost =)

snippety se pojmenovávají z důvodu toho když máš na stránce víc snippetů a potřeboval bys přepsat jenom jeden.

Je divný že data to pošle správný ale nepřekreslí to, to vypadá na chybu JS :/ ale možná chybí někde zavináč… máš @{include #content} ?

Editoval dRaGen (18. 11. 2009 17:51)

kamil
Člen | 14
+
0
-

nikde nemám @{include #content} protože to tam dávám jako widget
JS chybu mi firebug nehlásí

Tomik
Nette Evangelist | 485
+
0
-

Pokud firebug vypíše správný obsah, je chyba v JS části. Zkus to nějak krokovat, či vypisovat průběžně. Ať zjistíš, kde to dělá chybu…

redhead
Člen | 1313
+
0
-

opravdu to spíš je chyba JS, si to projeď ve Firebugu krokováním…

resp. v JS bude chyba viditelná, ale příčina může být v php.

Ondřej Mirtes
Člen | 1536
+
0
-

Konstruktor rodiče Controlu by se určitě volat měl, doplň do něj

parent::__construct($presenter, $view); //myslím, že originálně se ty parametry jmenují parent a name

invalidateControl v továrničce je nesmysl, ale nijak by to funkčnost ovlivnit nemělo.

Jak vypadá vypsaná odpověď ve Firebugu? Zkopči ji sem nebo ukaž screenshot. Možná, že javascript zmate ten dump, bude považovat ten JSON za poškozený a proto neupdatuje snippet.

Editoval Ondřej Mirtes (18. 11. 2009 18:28)

kamil
Člen | 14
+
0
-

Díky borci, problém byl samozřejmě v tom, že jsem si tam dělal pomocné výpisy pomocí Debug::dump. Pokud jsem je odstranil tak vše fungovalo.

Tady je původní js odpověď.

<pre class="dump"><span>NULL</span>
</pre>
<pre class="dump"><span>string</span>(4) "bagr"
</pre>
<pre class="dump"><span>array</span>(2) <code>{
   0 => <span>string</span>(7) "default"
   1 => <span>string</span>(8) "Homepage"
}</code>
</pre>
{"state":[],"snippets":{"content__":"        22584\n"}}

ještě jednou děkuju

kamil
Člen | 14
+
0
-

Objevily se mně ale dva jiné problémy:

V metodě handleTest si něco uložím do nějaké vlastnosti a v metodě render to nikdy není k dispozici. Jako kdyby se handleTest volal na jiné metodě než render. Nechápu co dělám špatně.

Další problém je, že $param metody handle mi vždy přijde jako NULL, taky nevím proč a je celkem jedno jestli mu dám ve spouštěcím odkazu parametr 1, 2 nebo kterýlikov jiný.

Ondřej Mirtes
Člen | 1536
+
0
-

kamil napsal(a):

Objevily se mně ale dva jiné problémy:

V metodě handleTest si něco uložím do nějaké vlastnosti a v metodě render to nikdy není k dispozici. Jako kdyby se handleTest volal na jiné metodě než render. Nechápu co dělám špatně.

Další problém je, že $param metody handle mi vždy přijde jako NULL, taky nevím proč a je celkem jedno jestli mu dám ve spouštěcím odkazu parametr 1, 2 nebo kterýlikov jiný.

Že se ti nepředá parametr je právě tím nezavolám konstruktoru rodiče.

Jinak co v handle* přiřadíš do šablony, tak v render k dispozici samozřejmě máš.

kamil
Člen | 14
+
0
-

Jestli tě chápu správně tak oba problémy mají jedno řešení a tím je zavolání konstruktoru rodiče. Ale jak to mám správně udělat? Mám to volat ručně nebo vynechávám nějaký důležitý krok a nevím o tom?

Ondřej Brejla
Člen | 746
+
0
-

Vždyť už ti to Ondřej psal, tak tedy ještě jednou:

public function __construct($presenter = null, $view = null) {
        /* $parent - ordicovsky presenter (komponenta), tedy tvuj $presenter */
	parent::__construct($presenter, 'Content');

	$this->presenter = $presenter;
	$this->view = $view;
}

Editoval Ondřej Brejla (19. 11. 2009 14:59)

kamil
Člen | 14
+
0
-

ok, diky, vše jsem upravil a opravil, parametry mi už chodí,ale nic co si v handle zapíšu v renderu k dispozici nemám.
Dokonce ani když to použiju jako persistent parametr podle příkladu Fifteen.

Prosím poraďte…

kamil
Člen | 14
+
0
-

Přišel jsem na to kde mám problém, je následující:

Odkaz na handleTest se vypisuje v komponentě Menu, takže je tam továrnička
Zatímco obsah se vykresluje v šabloně @layout.html, do které posílám data přes HomepagePresenter.

Po ajaxovém dotazu tedy dojde k tomu, že handleTest se zavolá na Contentu vytvořeném továrničkou v komponentě Menu a render se zavolá na Contentu vytvořeném továrničkou v presenteru HomepagePresenter.

Dalo by se to nějak vyřešit, nenapadá vás někoho něco?

David Grudl
Nette Core | 8228
+
0
-

V celém kódu bych udělal víc úprav.

  1. komponenta může mít rodiče, ale ten nemusí být nutně presenter, hierarchie může být složitější. Proto je v konstruktoru vhodnější psát $parent místo $presenter. Zároveň $parent není potřeba lokálně ukládat, protože už třída Component ho ukládá a přístupňuje metodou getParent(). Presenter je dostupný přes metodu getPresenter() třídy PresenterComponent.
  2. aby presenterové komponenty fungovaly zcela správně, musí být zavolán konstruktor třídy PresenterComponent. Tudíž pokud přepisuji konstruktor, musím vždy volat parent::__construct().
  3. volat parent::__construct($presenter, 'Content'); je nesmysl, druhý parameter (jméno komponenty) by tak fixně vytvářel komponentu s názvem Content, nicméně komponenta nemůže rozhodovat o svém názvu, takže je lepší volat třeba jen parent::__construct(); nebo si $name předat v konstruktoru a volat parent::__construct($parent, $name). S tím zřejmě souvisí chyba zmíněná v posledním komentáři.