Problémy s AJAX vs. komponenta
- kamil
- Člen | 14
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
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)
- Ondřej Mirtes
- Člen | 1536
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
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
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
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áš.
- Ondřej Brejla
- Člen | 746
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
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
V celém kódu bych udělal víc úprav.
- 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.
- 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().
- volat
parent::__construct($presenter, 'Content');
je nesmysl, druhý parameter (jméno komponenty) by tak fixně vytvářel komponentu s názvemContent
, nicméně komponenta nemůže rozhodovat o svém názvu, takže je lepší volat třeba jenparent::__construct();
nebo si $name předat v konstruktoru a volatparent::__construct($parent, $name)
. S tím zřejmě souvisí chyba zmíněná v posledním komentáři.