Zajaxování divu, buttonu, jak na to?
- Freestyler
- Člen | 50
Ahoj,
pokouším se zAJAXovat jednu komponentu, respektive výpis z ní. Je to
selectBox který vypíše seznam článků v dané kategorii. Komponenta je
vytvořena přes interface, ale to by nemělo hrát roli. Problém je, že pokud
něco vyberu v selectBoxu, tak se mi sice v pořádku zobrazí co chci, ale
překlikne se vybraná položka na první kolonku, takže vlastně nevím co
mám vybráno, chtěl bych to obejít AJAXem, aby se reloadoval jen <div>
do kterého se obsah vykresluje. Koukal jsem na přednášku Vojty Dobeše,
pochopil jí, ale ani tak mi to nefunguje.
Nechám mluvit kód:
@layout.latte (nevím, jestli to jde takhle použít na <div> a nebo to musí být odkaz
<script>
$("div.ajax").live("click", function (event) {
event.preventDefault();
$.get(this.href);
});
</script>
HomepagePresenter
public function createComponentArticleMenu()
{
$control = $this->articleMenuFactory->create();
$control['articleMenu']->onSuccess[] = function($form) {
if ($this->isAjax()) {
$this->invalidateControl('articles');
}
else {
$this->redirect('this', array('category' => $form->values->category));
}
};
return $control;
}
default.latte (k HomepagePresenteru)
{block content}
<br /> <br />
<div class="main"><h3>Posledních 10 příspěvků:</h3> <br />
{control articleMenu}
{snippet articles}
<br /> <br />
<div class="ajax">
<table class="table-article-create">
<thead>
<tr>
<th>ID</th>
<th>Název</th>
<th>Text</th>
<th>Autor</th>
<th>Datum</th>
<th>Kategorie</th>
</tr>
</thead>
<tbody>
<tr n:foreach = "$articles as $article">
<td>{$article->id}</td>
<td>{$article->title|striptags}</td>
<td class="content">
<span class='icons'>
<a n:href='Articles:edit $article->id'><img src="{$basePath}/images/icons/edit.png" /></a>
<a n:href='Articles:delete $article->id'><img src="{$basePath}/images/icons/close-tab.png" /></a>
</span>
{!$article->content|substr:0,35|striptags}
</td>
<td>{$article->author ? $article->author:('Neznámý')}</td>
<td>{$article->datetime}</td>
<td>{($category = $article->ref('categories','categories_id')) ? $category->name:('Nezařazeno')}</td>
</tr>
</tbody>
</table>
{/snippet}
</div>
{/block}
Díky za nápady, bude tam někde nějaká kravina, ale nemůžu na ní přijít. Script od Honzy Marka includovaný mám.
- Tomáš Votruba
- Moderator | 1114
Ahoj, pro zajaxování použij nette.ajax.js.
Aktivuj:
$(function () {
$.nette.init();
});
A pak k odkazu přidej class="ajax"
.
Mělo by to jet.
Editoval Tomáš Votruba (3. 8. 2014 23:01)
- Freestyler
- Člen | 50
Použil jsem, ale nefunguje. Nevím jak to napsat pro ten <div> co tam mám. To co chci ajaxovat, resp. má to být akce při kliknutí na button je komponenta, kterou nevykresluju ručně, ale přes {control}.
Momentálně tedy to mám takhle: http://pastebin.com/8Ctmc5Z6
Nechci tu moc spamovat, tak pastebin :).
Dále nevím jestli někde musím zjišťovat jestli je to Ajax nebo ne ($this->isAjax()), popř. někde se používá $this->invalidateControl(), který je teď deprecated, takže je v tom všem fakt zmatek :(.
Tomáš Votruba napsal(a):
Ahoj, pro zajaxování použij nette.ajax.js.
Aktivuj:
$(function () { $.nette.init(); });
A pak k odkazu přidej
class="ajax"
.Mělo by to jet.
- Zax
- Člen | 370
<div class="ajax">
jsem ještě nikdy neviděl, jak psal
@TomášVotruba, class="ajax"
patří do odkazu,
nette.ajax.js si to pak pošéfuje. Teď si nepamatuji, jak je to
u formulářů (mám to zapouzdřené do
$form->enableAjax()
) – buď by mělo stačit přidat
class="ajax"
celému formuláři, nebo na submit. Jedno z toho by
mělo jít ;-)
Každopádně, element (nemusí to být nutně div), který chceš reloadovat === snippet.
invalidateControl()
a validateControl()
jsou
deprecated a místo nich se používá metoda redrawControl()
,
jejíž název dává mnohem větší smysl.
Snad jsem aspoň trochu pomohl.
- Freestyler
- Člen | 50
Tak asi budu potřebovat nakopnout víc, než jsem myslel.
Tady tvořím komponentu:
protected function createComponentArticleMenu() {
$form = new Form();
$form->addSelect('category','Kategorie', $this->articles->getArticleCategories()->fetchPairs('id', 'name'))
->setPrompt('Všechny články');
$form->addSubmit('submit', 'Zobrazit');
return $form;
}
Snippet je v tom pastebinu předtím, pro úplnost http://pastebin.com/8Ctmc5Z6. Kam teda mám nacpat class=‚ajax‘? Komponentu nevykresluji ručně, ale přes {control articleMenu}, což je vidět i v tom pastebinu, stejně tak naincludovaný init.
Nechci ajaxovat komponentu, ale výsledek z té komponenty, což je tabulka se seznamem článků z DB.
To se děje zde:
<?php
namespace AdminModule;
/**
* Homepage presenter.
*/
class HomepagePresenter extends BasePresenter
{
/**
* @var \App\Components\IArticleMenuFactory
* @inject
*/
public $articleMenuFactory;
/** @persistent */
public $category;
/**
*
* @return ArticleMenu
*/
public function createComponentArticleMenu()
{
$control = $this->articleMenuFactory->create();
$control['articleMenu']->onSuccess[] = function($form) {
$this->redirect('this', array('category' => $form->values->category));
};
return $control;
}
public function renderDefault() {
if($this->category) {
$this->template->articles = $this->articles->getArticleByCategoryId($this->category);
} else {
$this->template->articles = $this->articles->fetchAll();
}
}
}
Tím pádem nevím ani kam dát $this->redrawControl('articles);
Díky moc, jsem asi dost natvrdlej :(
- Zax
- Člen | 370
Zkus do createComponentArticleMenu()
přidat
$form->getElementPrototype()->addClass('ajax');
Formulář musíš zajaxovatět, jinak se ti prostě ajaxově nepošle. To, že po odeslání chceš jen překreslit konkrétní snippet, dáš najevo právě tím redrawControl().
EDIT: redrawControl() patří do onSuccess (resp. obecně do signálů), což máš správně ;-)
Editoval Zax (4. 8. 2014 22:11)
- Freestyler
- Člen | 50
Form už má class ajax, to je v pohodě, ale když kouknu do firebugu, tak v síti nikde nevidím, že by tam byl nějakej JSON :(.
redrawControl jsem hodil sem
public function renderDefault() {
if($this->category) {
$this->template->articles = $this->articles->getArticleByCategoryId($this->category);
$this->redrawControl('articles');
} else {
$this->template->articles = $this->articles->fetchAll();
}
→ takže by se měl provést při vykreslování článků a danýho snippetu
Každopádně to pořád nechodí a chybu už tam nikde nevidím :/
Zax napsal(a):
Zkus do
createComponentArticleMenu()
přidat
$form->getElementPrototype()->addClass('ajax');
Formulář musíš zajaxovatět, jinak se ti prostě ajaxově nepošle. To, že po odeslání chceš jen překreslit konkrétní snippet, dáš najevo právě tím redrawControl().
EDIT: redrawControl() patří do onSuccess (resp. obecně do signálů), což máš správně ;-)
- Zax
- Člen | 370
Ale nééé, redrawControl nepatří do render, ale do signálu :-)
Když otevřeš stránku neajaxově, tak ti ta metoda redrawControl v renderu neudělá vůbec nic. Nevím, jestli by to ajaxově takhle fungovalo, ale mám pocit, že v renderu je na redrawControl pozdě, je třeba využít toho, že se signály provádí dřív, než render.
Po odeslání formuláře (což proběhne ajaxově, pokud má form
class=„ajax“) se zavolá ta tvoje funkce
$control['articleMenu']->onSuccess[] = function...
, což je
klasický signál (byť to tak na první pohled možná nevypadá) a proto máš
jistotu, že se provede dřív, než render. V tom signálu tedy provedeš
vše, co je potřeba (změníš stav – nastavíš kategorii) a označíš
snippet k překreslení pomocí redrawControl().
Vidím, že tam děláš redirect se změnou persistentního parametru –
redirect se ale při ajaxu neprovede (resp. provede se klasický neajaxový
redirect), proto tam musí být to if($this->isAjax())
. Já bych
to zkusil třeba takto:
// tohle je ta tvoje onSuccess funkce
if($this->isAjax()) { // pokud je to ajax
$this->category = $form->values->category; // nastav kategorii
$this->redrawControl('articles'); // a označ snippet 'articles' k překreslení pomocí ajaxu
} else { // pokud není ajax, proveď klasický redirect
$this->redirect('this', array('category' => $form->values->category));
}
Ještě jedna věc – název redrawControl() je možná trošku zavádějící, ono se neprovede okamžité překreslení, jen se označí daný snippet k překreslení a Nette k tomu přihlíží až během vykreslování („Hele, Nette, až budeš někdy v budoucnu vykreslovat tuto komponentu, tak ji nevykresluj celou, ale místo toho mi pošli tento snippet“ – a je blbost toto po Nette chtít až během vykreslování ;-)).
Příspěvek ber s rezervou, nejsem žádný Nette guru a možná jsem plácnul i pár blábolů, ale s Ajaxem jsem si hrál celkem dost.
- CZechBoY
- Člen | 3608
No já tam vidim control leda na menu.
Jestli chceš ajaxovat jen ten výpis článků tak dej ten výpis článků do
snippetu.
šablona komponenty
{snippet articlesContainer}
<div n:foreach="$articles as $article" class="article">
<h4>{$article->heading}</h4>
<div class="date">{$article->date}</div>
<div class="text">{$article->text}</div>
</div>
<a class="ajax" n:if="$page" n:href="next! $page">Další strana</a>
{/snippet}
Komponenta
/** @var int */
private $page = 1;
public function handleNext($page) {
$this->page = $page;
if ($this->presenter->isAjax()) { // musí tu být vůbec presenter?
$this->redrawControl();
}
}
public function render() {
$this->template->articles = $data_z_databaze->page($this->page);
$this->template->page = $jsou_dalsi_data_k_dispozici ? $this->page + 1 : false;
$this->template->setFile(...);
$this->template->render();
}
- Freestyler
- Člen | 50
Pecka, sice jsem si to trošku upravil, ale už to funguje jak má :). Díky moc moc moc!!!
Zax napsal(a):
Ale nééé, redrawControl nepatří do render, ale do signálu :-)
Když otevřeš stránku neajaxově, tak ti ta metoda redrawControl v renderu neudělá vůbec nic. Nevím, jestli by to ajaxově takhle fungovalo, ale mám pocit, že v renderu je na redrawControl pozdě, je třeba využít toho, že se signály provádí dřív, než render.
Po odeslání formuláře (což proběhne ajaxově, pokud má form class=„ajax“) se zavolá ta tvoje funkce
$control['articleMenu']->onSuccess[] = function...
, což je klasický signál (byť to tak na první pohled možná nevypadá) a proto máš jistotu, že se provede dřív, než render. V tom signálu tedy provedeš vše, co je potřeba (změníš stav – nastavíš kategorii) a označíš snippet k překreslení pomocí redrawControl().Vidím, že tam děláš redirect se změnou persistentního parametru – redirect se ale při ajaxu neprovede (resp. provede se klasický neajaxový redirect), proto tam musí být to
if($this->isAjax())
. Já bych to zkusil třeba takto:// tohle je ta tvoje onSuccess funkce if($this->isAjax()) { // pokud je to ajax $this->category = $form->values->category; // nastav kategorii $this->redrawControl('articles'); // a označ snippet 'articles' k překreslení pomocí ajaxu } else { // pokud není ajax, proveď klasický redirect $this->redirect('this', array('category' => $form->values->category)); }
Ještě jedna věc – název redrawControl() je možná trošku zavádějící, ono se neprovede okamžité překreslení, jen se označí daný snippet k překreslení a Nette k tomu přihlíží až během vykreslování („Hele, Nette, až budeš někdy v budoucnu vykreslovat tuto komponentu, tak ji nevykresluj celou, ale místo toho mi pošli tento snippet“ – a je blbost toto po Nette chtít až během vykreslování ;-)).
Příspěvek ber s rezervou, nejsem žádný Nette guru a možná jsem plácnul i pár blábolů, ale s Ajaxem jsem si hrál celkem dost.