Komponenta zpracuje signál, ale nepřekreslí se
- kytart
- Člen | 10
Mám na stránce několikrát jednu komponentu (používám UI\Multiplier) a tato komponenta obsahuje tlačítko které odešle signál. Poté se má komponenta překreslit. Jednoduché jak facka, přesto mi to nefunguje.
Šablona komponenty je velmi jednoduchá (pro potřeby tohoto dotazu stačí takto):
{snippet}
<a n:class="ajax" n:href="signal! $id">button</a>
{/snippet}
Metoda pro zpracování signálu:
public function handleSignal($id) {
$this->model->doSomething();
if($this->presenter->isAjax()) {
$this->invalidateControl();
} else {
$this->redirect('this');
}
}
Problém je v tom, že se signál normálně odešle a zpracuje, následně
se celá komponenta invaliduje, ale nepřekreslí se. V konzoli se vypíše,
že došlo k nějaké chybě při odesílání požadavku.
Došel jsem k názoru, že problém bude nejspíš v tomto:
public function render($data) {
// some code
}
Předpokládám, že poté, co se komponenta invaliduje, odešle se
požadavek na html, ale nepošlou se žádná data jako argument, tím pádem
dojde k fatální chybě a komponenta se nepřekreslí.
Mám tedy dvě otázky:
- Je problém opravdu tam kde si myslím že je?
- Pokud ano, jak se to dá řešit? Pokud ne, kde jinde by mohl být?
Díky moc
- kytart
- Člen | 10
na1k napsal(a):
V konzoli se vypíše, že došlo k nějaké chybě při odesílání požadavku.
Tohle je dost vágní. K jaké chybě? Na straně server? 50× u ajax requestu?
Pokud ano, ve složce s logy bys měl najít uloženou výjimku.
Tak skutečně ve složce s logy vyjímka byla a potvrzuje mojí hypotézu. Metoda render() očekává argument, ale ten se nedodá…
- Vojtěch Dobeš
- Gold Partner | 1316
Chybu jsi vydedukoval zcela správně. Předávání parametrů metodě
render
bohužel s AJAXem není kompatibilní. Pokus se ta data
předávat v továrničce nebo někde v presenteru/nadřazené komponentě,
kde je máš k dispozici a můžeš ke komponentě přistoupit.
- kytart
- Člen | 10
vojtech.dobes napsal(a):
Pokus se ta data předávat v továrničce nebo někde v presenteru/nadřazené komponentě, kde je máš k dispozici a můžeš ke komponentě přistoupit.
Vyřešil jsem to následujícím způsobem:
public function render($data = null) {
if($data != null) $this->dataToTemplate($data);
$this->template->render();
}
public function handleVote($id) {
$this->model->doSomething($id);
if($this->presenter->isAjax()) {
$data = $this->anotherModel->getData($id);
$this->dataToTemplate($data);
$this->invalidateControl();
} else {
$this->redirect('this');
}
}
private function dataToTemplate($data) {
$this->template->something = $data->something;
// dalsi promenne do sablony
}
Bohužel se objevil další problém. Konzole teď ukazuje, že požadavek
proběhl úspěšně, jenže response je {"state": []}
a nic
jiného… Tj. server v pořádku zpracoval požadavek, zavolal metodu render
komponenty, protože se invaliduje (nebo by alespoň měl), ale šablona se
nevykreslí… To už vůbec nechápu
- kytart
- Člen | 10
Nakonec jsem na to po čase přišel sám, tak to sem dám, aby to tu bylo,
kdyby někdo narazil na podobný problém.
Problém byl v tom, že předávám jako parametr pro render() celé pole.
Řešení z minulého příspěvku by teoreticky mělo fungovat taky, jenže
nefungovalo. Proto jsem to obešel následujícím způsobem:
public function render($id = null) {
if($id != null) $this->getData($id);
$this->template->render();
}
public function handleSignal($id) {
$this->model->doSomething($id);
if($this->presenter->isAjax()) {
$this->getData($id);
$this->invalidateControl();
} else {
$this->redirect('this');
}
}
protected function getData($id) {
$data = $this->modelOther->getDataArray($id);
$this->template->value1 = $data->value1;
// dalsi promenne do sablony
}
tedy řešení spočívá v tom, že ani v metodě render() ani nikde jinde nepředávám metodě celé pole, ale pouze ID a až následně podle ID získám data z databáze a nasypu do šablony. Hotovo!
- fabian
- Člen | 20
Ahoj,
myslim, ze jsem ted resil stejny problem: pokud ma render() metoda
controlu nejaky parametr, po prekresleni snippetu ajaxem se ji tento parametr uz
znovu nedostane, takze nemuze udelat svoji praci a odeslat payload.
Skonci chybou napr. Fatal error: Missing argument 1 for
PostRateControl::render() (treba to nekomu pomuze pri googleni;)
Ja to vyresil takhle:
class PostRateControl extends \Nette\Application\UI\Control
{
private $postId;
public function render($postId = NULL)
{
if (!is_null($postId)) { // nastavujeme $postId, pokud je control volan ze sablony {control postRateControl, 1} napr.
$this->postId = $postId;
}
if (is_null($this->postId)) { // takova pojistka:)
throw new Exception('no post id');
}
...
nejake veci, co ma metoda render obstarat a poslat sablone
...
return $this->template->render();
}
public function handleRate($postId, $rate)
{
$this->postId = $postId; // nastavime privatni promennou postId, kterou pouzije metoda render() po invalidaci
...
tady si vyresime zapis hodnoceni ..
...
if ($this->presenter->isAjax()) {
$this->invalidateControl();
}
}
}