Komponenta není při ajaxovém dotazu vracena v JSON odpovědi a nevykreslí se
- josef.sabl
- Člen | 153
Mám takovouto jednoduchou komponentu:
class Test extends \Nette\Application\UI\Control
{
/** @persistent */
public $test = 0;
public function render()
{
$this->template->setFile(__DIR__ . '/test.latte');
$this->template->test = $this->test;
$this->template->render();
}
public function handleReload()
{
$this->test = rand(1000, 9999);
$this->redrawControl();
}
}
S takovouto jednoduchou šablonou:
{$test}
<a n:href="reload" n:class="ajax">reload</a>
Takto ji vytvářím v presenteru:
class HomepagePresenter extends BasePresenter
{
public function createComponentTest()
{
return new Test;
}
}
A takto vkládám do default.latte:
{block content}
{control test}
Ale když kliknu na odkaz reload, který má vygenerovat nové náhodné číslo a poslat překreslenou komponentu, dostanu jen takovouto odpověď:
{"state":{"test-test":3497}}
Neobsahuje tedy nové HTML komponenty a komponenta se nepřekreslí.
Poradíte prosím, co dělám špatně?
Předem děkuji.
Nette 2.2.2 released on 2014–06–26
Editoval josef.sabl (7. 7. 2014 15:51)
- Oli
- Člen | 1215
Chybí ti tam snippety.
Záleží na tom, kde chceš invalidovat. Můžeš v komponentě nebo
v presenteru. Pokud chceš v presenteru tak:
komponenta
public function handleReload()
{
$this->test = rand(1000, 9999);
$this->presenter->redrawControl('testSnippet'); // <--- voláno nad presenterem
}
default.latte
{block content}
{snippet testSnippet} {* <--- mnůže být jakýkoli název, ten potom voláš v tom redrawControl *}
{control test}
{/snippetn}
Pokud by jsi to chtěl nechat celé na té komponentě, tak je to velmi
podobné, jen se to všechno přesune do komponenty
komponenta:
public function handleReload()
{
$this->test = rand(1000, 9999);
$this->redrawControl('testSnippet');
}
template komponenty
{snippet testSnippet}{$test}{/snippet}
<a n:href="reload" n:class="ajax">reload</a>
btw. předpokládám, že používáš nějakej js doplněk, například nette.ajax.js?
- David Kudera
- Člen | 455
Plus navíc pokud máš např. jen jeden snippet přes celou komponentu (nehodí se moc pro velké komponenty), je možný název snippetu úplně vynechat.
{snippet}{$test}{/snippet}
<a n:href="reload" n:class="ajax">reload</a>
public function handleReload()
{
$this->test = rand(1000, 9999);
$this->redrawControl();
}
toto se použije uvnitř komponenty, ne presenteru
- josef.sabl
- Člen | 153
Díky vám oběma za radu. Vzorová zjednodušená komponenta mi funguje, ale moje reálná stále ne :-) Ona je tam ta situace trošku složitější.
Mám totiž více komponent, jednu hlavní, která zajišťuje komunikaci mezi podkomponentami. Zase to zjednoduším:
Hlavní komponenta:
class Test extends \Nette\Application\UI\Control
{
/** @persistent */
public $test = 0;
public function render()
{
//bez této funkce to hází chybu, je to příčina?
}
public function reload()
{
$this->test = rand(1000, 9999);
$this->redrawControl();
$this->getComponent('foo')->redrawControl();
}
public function createComponentFoo()
{
return new TestFoo();
}
}
Podřízená komponenta:
class TestFoo extends \Nette\Application\UI\Control
{
public function render()
{
$this->template->setFile(__DIR__ . '/test.latte');
$this->template->test = $this->getParent()->test;
$this->template->render();
}
public function handleReload()
{
$this->getParent()->reload();
}
}
Hlavní komponenta nemá šablonu, není vizuální. Podkomponenta má takovouto šablonu (nyní již obalenou snippetem)
<span n:snippet>{$test}</span>
<a n:href="reload" class="ajax">test</a>
V šabloně presenteru je použitá takto:
{block content}
{control test-foo}
PS: Ano, používám nette.ajax.js
- josef.sabl
- Člen | 153
Tak už vím :) Příčina je skutečně v té prázdné render metodě, která nic nedělá a komponenta tedy reálně nepřekreslí ani podkomponenty, které pak nepošle. Zkoušel jsem volat redrawControl() na presenteru, ale to nepomohlo.
Nakonec zabralo doplnění speciální šablony pro hlavní komponentu, která se sice při běžném renderování nikde nevyužije, ale při renderování subrequestu pro ajax se použije pro vygenerování šablony pro podkomponentu.
Takže hlavní komponenta:
class Test extends \Nette\Application\UI\Control
{
/** @persistent */
public $test = 0;
public function render()
{
$this->template->setFile(__DIR__ . '/test.latte');
$this->template->render();
}
public function reload()
{
$this->test = rand(1000, 9999);
$this->redrawControl();
$this->getComponent('foo')->redrawControl();
}
public function createComponentFoo()
{
return new TestFoo();
}
}
A její šablona:
{control foo}