Invalidace renderu z jiné akce?
- Kcko
- Člen | 468
Ahoj,
Presenter → 2 akce nebo rendery (to je fuk)
Default – výpis položek
Detail – detail položek
Na stránce bude vyhledávací pole, které omezí / vyfiltruje výpis položek. Dojde tedy k invalidaci snipetu v Default akci. To je OK.
Ale pokud budu na detailu položky, netuším, jak bez přesměrování na default to také udělat AJAXEM (bez refreshe). Ideálně aby se mi měnila i URL (možná existuje nějaká extenze).
Díky za popostrčení.
- Kcko
- Člen | 468
Změny URL po AJAXovém requestu řeší nette.history.ajax od
@VojtěchDobeš
A co se týká onoho překreslení snippetu, tak stačí mít v obou
šablonách (default/detail) stejný snippet a pak jej invalidovat.
Už mi nefunguje akorát „přesměrování“. Potřebuji vyvolat handle a
přesměrovat na nějakou akci s nějakým parametrem.
Lze to?
- MajklNajt
- Člen | 494
ahoj, čo tak kúsok kódu, pretože napr. mne stále nie je jasné, čo sa snažíš dosiahnuť – v prvom príspevku píšeš „bez presmerovania“, teraz zase „nefunguje presmerovanie“… btw. ja vyhľadávanie, ktoré je umiestnené vo viacerých šablónach, riešim cez komponentu ⇒ nemusím tak ten istý formulár renderovať a obaľovať snippetom na 5 miestach
- Kcko
- Člen | 468
MajklNajt napsal(a):
Ahoj, vyznívá to zmateně, protože jsem něpočítal s vyhledávacím
formulářem.
Popíši to znovu:
Jedná se o výpis gistů (jsem napojen na API githubu a stahuju si pro svoji potřebuju svoje gisty, které mají štítky atd.) (vypadá to nějak takhle): http://bit.ly/2DivrAK
Celý kód asi není potřeba, je to základní logika a základní práce s Nette:
- 1 presenter
- 2 render metody (default = pro výpis gistů, detail pro detail gistu s jeho náležitostmi)
Vše mi funguje, vše OK.
Chci tam i vyhledávání a líbilo by se mi, aby fungovalo skrze ajax + nějaký preloader (ten si dodělám přes extenzi do nette.ajax.js).
Na vyhledávácí formulář není potřeba komponenta, stačí jednoduchá továrnička v presenteru.
Takže napíši něco do vyhledávacího inputu, odešlu formulář AJAXem, obslužný handle to zpracuje a potřebuji se dostat na
- na 3 render<Search> s (parametrem $q = hledaný výraz).
Kdyby to nebylo ajaxem, tak prostě
<?php
$this->redirect("search", $q);
?>
Ale jak to udělat s ajaxem? Když si vygeneruji testovací odkaz ručně
<a n:href=„search tracy“
class=„ajax“>testovací</a>
⇒ vygeneruje se URL <web>/gists/search/tracy a jelikož
mám v šabloně , stejně jako v ostatních dalších 2, nadřazený div,
který je snippetem, tak provedu invalidaci a funguje to.
Ale nevím, jak to udělat, když potřebuji v Nette přesměrovat z handlu
na nějaký render s parametrem bez refreshe?
Nebo by stačilo, abych uměl nějak vyvolat nějaký request, který se děje
kdybych ten odkaz udělal ručně viz (search tracy)
Editoval Kcko (11. 11. 2018 9:39)
- Phalanx
- Člen | 310
@Kcko Odešli vyhledávací formulář ajaxem, přiřaď hodnotu z vyhledávání do persistentního parametru a dej redrawControl(‚tvujSnippet‘)
Poslat ho můžeš buď přes submit button
<input type="text" name="search">
<input type="submit" name="submit" class="ajax">
nebo si na to napíšeš javascriptové odeslání přes $.nette.ajax post. Záleží na tobě.
Nefunguje ti to kvůli tomu, že tam máš jen odkaz místo poslání formuláře nebo poslání přes javascript.
Editoval Phalanx (11. 11. 2018 11:47)
- Kcko
- Člen | 468
Phalanx napsal(a):
@Kcko Odešli vyhledávací formulář ajaxem, přiřaď hodnotu z vyhledávání do persistentního parametru a dej redrawControl(‚tvujSnippet‘)
Poslat ho můžeš buď přes submit button
<input type="text" name="search"> <input type="submit" name="submit" class="ajax">
nebo si na to napíšeš javascriptové odeslání přes $.nette.ajax post. Záleží na tobě.
Nefunguje ti to kvůli tomu, že tam máš jen odkaz místo poslání formuláře nebo poslání přes javascript.
Ahoj, předně dík za reakci.
Kdyby to nebylo AJAXEM tak
- jsem v renderDefault nebo renderDetail (to je uplně jedno).
- Vyhledávací formulář , něco napíši klik … ⇒ vyvolá se subrequest (tj. handle formuláře) a přesměruji na renderSearch($q)
- v renderSearch si přes model zobrazím gisty, které obsahují hledaný výraz.'
Nějak nechápu v čem mi persistentní parametr pomůže. Já samozřejmě chápu, že odkaz je odkaz a já tu řeším něco jiného :-)
Já se prostě ptám, jestli jde nějak AJAXově přesměrovat z jednoho
renderu na druhý bez refreshe.
Pokud ne, tak samozřejmě asi půjde v případě AJAXu bod 2 upravit
tak, že
<?php
function handleSearchForm($form, $values)
{
if ($this->isAjax())
{
$this->template->gists = $this->model->findGistBySearch($values->q);
$this->redrawControl("gists");
}
else
{
$this->redirect("search", $values->q);
}
}
function renderSearch($q)
{
$this->template->gists = $this->model->findGistBySearch($values->q);
// ... atd
}
?>
Tohle asi bude fungovat, ale není to to co jsem chtěl, tady dělám díky AJAXU 2× to samé (a defakto to jsou 2 různá URL, handle a render).
Takže moje otázka pořád zní:
„Já se prostě ptám, jestli jde nějak AJAXově přesměrovat z jednoho renderu na druhý bez refreshe.“
Díky :-)
- Felix
- Nette Core | 1196
„Já se prostě ptám, jestli jde nějak AJAXově přesměrovat z jednoho renderu na druhý bez refreshe.“
Moc nerozumim co je timhle mysleno.
Jestli myslis predat request, interne v Nette, z jedne action/render metody
do druhe, v ramci jednoho requestu, tak na to slouzi
$presenter->forward()
.
- Kcko
- Člen | 468
Felix napsal(a):
„Já se prostě ptám, jestli jde nějak AJAXově přesměrovat z jednoho renderu na druhý bez refreshe.“
Moc nerozumim co je timhle mysleno.
Jestli myslis predat request, interne v Nette, z jedne action/render metody do druhe, v ramci jednoho requestu, tak na to slouzi
$presenter->forward()
.
Ano to je ono. Zbývá dořešit jednu věc a tou je to, že i když mám nalinkovaný nette.history.ajax (který normálně funguje) tak v případě handlu mi přidá GET parametr ?do=test, snippet se mi ovšem správně překreslí, jen ta URL je blbě.
<web>/gist/34?do=test // detail gistu s přidaným handlem
<?php
// jen na otestovani
public function handleTest()
{
if ($this->isAjax())
$this->forward('default', 'php'); // na <renderDefault> s argumentem $slug = php
}
?>
- Kcko
- Člen | 468
MajklNajt napsal(a):
Ja by som len poznamenal, že handle metóda je iba signál, čiže nemal by meniť action/view. Presmerovanie samo o sebe z jednej action na inú action bez refresha by ti mal plné vyriešiť nette.history.ajax
Jak? Jakým způsobem? Chci z handlu na akci/render, forward sice přesměruje, ale URL není taková jaká by být měla, viz předchozí reakce na Felixe.
Edit: v případe handlu formuláře, mi to history.ajax nezmění URL vůbec (je tam furt ta, ze které formulář ajaxově odesílám), což teda už není problém Nette, ale spíš té JS extenze, nevíte čím to je?
<?php
public function createComponentSearchForm()
{
$form = new UI\Form;
$form->getElementPrototype()->setClass('ajax');
$form->setMethod('GET');
$form->addText('q', 'Hledaný výraz')
->addRule($form::MIN_LENGTH, 'Nebuď línej a zadej něco', 2);
$form->addSubmit('_submit', 'Submit');
$form->onSuccess[] = function($form, $values) {
if ($this->isAjax())
$this->forward('default', NULL, $values->q);
else
$this->redirect('default', NULL, $values->q);
};
return $form;
}
?>
Editoval Kcko (11. 11. 2018 13:45)
- Kcko
- Člen | 468
MajklNajt napsal(a):
$this->redirect('default', NULL, $values->q);
by ti spolu s nette.history.ajax malo zmeniť url bez refreshu
Ano, je to tak, v response vidím (http://bit.ly/2Dgrdde), ale ted se mi zas nepřekreslí snippet :/
- Kcko
- Člen | 468
MajklNajt napsal(a):
A pri použití forward sa ti snippet prekreslí?
Ano, v response jsou snippety atd, překreslí. Při redirectu mám v reponse pouze redirect a URL, takže se nemá ani co překreslit.
Nikde jsem nenašel jak to má korektně fungovat, takže to nechám s tím forwardem a do payloadu si hodím současnou URL a poté stejně tak jak to dělá extenze history.ajax to přes JS vložím do URL (tj napíšu si svoji primitivní extenzi která bude z payloadu brát URL a vkládát ji do adresního řádku).
Nic jiného me už nenapadá a ani nerozumím tomu history.ajax chování.
- Kcko
- Člen | 468
Přikládám celý presenter:
<?php
namespace App\FrontModule\Presenters;
use App\Model,
App\FrontModule\Components,
Nette,
Nette\Application\UI;
class GistPresenter extends BasePresenter
{
/** @inject @var Model\Gist */
public $modelGist;
/** @inject @var Model\GistLabel */
public $modelGistLabel;
/** @inject @var Model\GistGistLabel */
public $modelGistGistLabel;
/** @inject @var Model\GistFile */
public $modelGistFile;
public function startup()
{
parent::startup();
$this['breadCrumbs']->add('Gists', $this->link('default'));
}
public function createComponentPaginator()
{
return new Components\VisualPaginator;
}
public function createComponentSearchGistForm()
{
$form = new UI\Form;
$form->getElementPrototype()->setClass('ajax');
$form->setMethod('GET');
$form->addText('q', 'Hledaný výraz')
->addRule($form::MIN_LENGTH, 'Nebuď línej a zadej něco', 2);
$form->addSubmit('_submit', 'Submit');
$form->onSuccess[] = function($form, $values) {
// if ($this->isAjax())
// else
//$this->invalidateControl();
$this->presenter->payload->url = $this->link('default', NULL, $values->q);
$this->redrawControl();
//$this->redirect('default', NULL, $values->q);
$this->forward('default', NULL, $values->q);
};
return $form;
}
public function renderDetail($guid)
{
$gist = $this->modelGist->findBy(array('id' => $guid))->fetch();
if (!$gist)
$this->error();
$this->template->heading = $gist->title;
$this->template->gist = $gist;
$this['breadCrumbs']->add($gist->title, $this->link('this'));
}
public function renderRaw($guid)
{
$gistFile = $this->modelGistFile->findBy(array('guid' => $guid))->fetch();
if (!$gistFile)
$this->error();
$this->template->gistFile = $gistFile;
}
public function actionDefault($slug = NULL, $q = NULL)
{
if ($this->isAjax())
{
$this->redrawControl();
}
}
public function renderDefault($slug = NULL, $q = NULL)
{
if ($this->isAjax())
{
$this->redrawControl();
}
$this->template->heading = 'Gists';
$gists = $this->modelGist->findAll();
if ($slug) {
$labelRow = $this->modelGistLabel->findAll()->where('slug', $slug)->fetch();
if (!$labelRow)
$this->error();
$gists->where(':gist_gist_label.gist_label_id', $labelRow->id);
$this->template->heading .= ' - ' . $labelRow->title;
$this['breadCrumbs']->add($labelRow->title, $this->link('this'));
}
// vyhledavani
if ($q)
{
$gists->where('
title LIKE ?
OR description LIKE ?
OR :gist_file.filename LIKE ?
OR :gist_file.content LIKE ?
',
'%'.$q.'%',
'%'.$q.'%',
'%'.$q.'%',
'%'.$q.'%'
);
}
$gists->order('updated DESC');
$vp = $this['paginator'];
$paginator = $vp->paginator;
$paginator->itemsPerPage = 20;
$paginator->itemCount = $gists->count("*");
$gists->limit($paginator->itemsPerPage,
$paginator->offset);
$this->template->gists = $gists;
}
public function handleTest()
{
if ($this->isAjax())
$this->forward('default', 'php'); // na <renderDefault> s argumentem $slug = php
}
public function beforeRender()
{
parent::beforeRender();
$this->template->labels = $this->modelGistLabel->findAll()->order('title ASC');
$this->template->labelsCnt = $this->modelGistGistLabel->findAll()
->select('COUNT(1) AS cnt, gist_label_id')
->group('gist_label_id')
->fetchPairs('gist_label_id', 'cnt');
}
}
Editoval Kcko (11. 11. 2018 17:22)
- Phalanx
- Člen | 310
@Kcko Nejjednodušší možný případ:
<?php
/** string|null @persistent */
public $q;
function handleSearchForm($form, $values)
{
$this->q = $values->q;
if ($this->isAjax())
{
// tento řádek tu volat nemusíš, protože redrawControl projde přes renderSearch
// $this->template->gists = $this->model->findGistBySearch($values->q);
$this->redrawControl("gists");
}
else
{
$this->redirect("search");
}
}
function renderSearch()
{
$this->template->gists = $this->model->findGistBySearch($this->q);
// ... atd
}
?>
Editoval Phalanx (12. 11. 2018 8:38)
- Kcko
- Člen | 468
@Phalanx Díky za reakci. Překreslí, ale nezmění URL.
Jak jsem zkoušel (předchozí moje komentáře) všechno možné, tak mi bud
jde změnit URL a nepřekreslí se snippet nebo obráceně.
Zkoušel jsem redirect nebo forward, zkoušel jsem zapnout history extenzi nebo
vypnout, posílat do payloadu URL, nic z toho nevede k chtěnému
výsledku:
- překreslit snippet (resp forwardnout na správný render s q parametrem)
- změnit url
Asi do toho hodíme vidle, nechci tady s tím otravovat do nekonečna.
Zkusím to vyřešit přesměrováním přes forward a vyřešit si tu změnu
URL sám přes vlastní extenzi, která jen nějak tupě nastavovat URL (škoda,
že to history extenze neřeší nebo je to prostě nefunkční).
Je zajímavé, že když použiji redirect, tak to history extenze pochopí, ale nepošle snipety a nemá se co překreslit.
Editoval Kcko (12. 11. 2018 10:47)
- Kcko
- Člen | 468
Phalanx napsal(a):
Promiň, pořád jsem tě nechápal. Zkus ještě poslední věc:
<?php if ($this->isAjax()) { $this->payload->url = $this->link('this', ['q' => $values->q]); $this->redrawControl('gists'); } else { $this->redirect('search', ['q' => $values->q]); } ?>
Z renderDetail to pořád zlobí, URL se změní, ale obsah zůstane
stejný.
Ze snippetu přijde pořád stejný obsah (tj renderDetail).
Už tomu fakt nerozumím.
Kašlem na to, holt ten Ajax oželím, díky za trpělivost a snahu to vyřešit.
Editoval Kcko (12. 11. 2018 13:01)