Snippet + ajax vyhledávání
- Filip023
- Člen | 13
Zdravím,
mám problém s rozběhnutí mého prvního snippetu. Chtěl jsem vyřešit
s jeho pomocí vyhledávání + následné překreslení nabídky, ale
z nějakého důvodu se mi nabídky nepřekreslí a zůstanou vždy ty co jsem
měl na začátku. Nevíte, kde by mohl být problém?
OfferPresenter.php
<?php
use Nette\Application\UI\Form,
Nette,
Model;
class OfferPresenter extends BasePresenter
{
private $offer;
protected function startup()
{
parent::startup();
$this->offer = $this->context->offer;
}
public function renderIndex()
{
$this->template->offers = $this->offer->findAll()->order('created DESC');
}
public function handleSearch($term)
{
$this->template->offers = $this->offer->find(7);
$this->redrawControl('results');
}
}
?>
šablona
<?php
{block content}
<div class="content" id="offer">
<h2>Nabídka</h2>
<div id="search_form">
{form searchForm}
{control $form errors}
{label text /}
{input text}
{label category_id /}
{input category_id}
{input search}
{/form}
</div>
{dump count($offers)}
<div class="left">
{snippet results}
{if count($offers) > 0}
{foreach $offers as $offer}
// telo pro zobrazeni nabidek
{/foreach}
{else}
<p>Aktuálně je naše nabídka prázdná!</p>
{/if}
{/snippet}
</div>
</div>
<script>
jQuery(window).ready(function() {
$('#frm-searchForm-text').on('change input', function () {
var value = $(this).val();
if (value.length >= 2) {
$.nette.ajax({
'url': '?do=search',
'data': {
term: value
}
});
}
});
});
</script>
{/block}
?>
Na počátku se mi vykreslí nabídky s ID 6 a 7, po napsání textu by se měla zobrazit jen 7, ale zůstanou obě.
- Filip023
- Člen | 13
Oli napsal(a):
Protože životní cyklus presenteru. Ten render ti překreslí handle
Dle toho jsem tedy změnit
<?php
public function renderIndex()
{
$this->template->offers = $this->offer->findAll()->order('created DESC');
}
?>
na:
<?php
public function actionIndex()
{
$this->template->offers = $this->offer->findAll()->order('created DESC');
}
?>
čímž se mi to již nepřepíše, v navrácených hodnotách to již vidím opravdu správně, ale na stránce jako takové se mi snippet stále nepřekreslí. Zůstávají pouze původní hodnoty.
Editoval Filip023 (27. 3. 2014 8:42)
- Filip023
- Člen | 13
Prosím o radu, pokouším se rozběhnout vyhledávání za pomocí snippetu, ale stále se mi nedaří zařídit, aby po kliknutí na vyhledávací tlačítko se překreslila nabídka produktů.
Akce pro vykreslení základní nabídky
<?php
public function actionIndex() {
$this->template->offers = $this->offer->findAll()->order('created DESC');
}
?>
Formulář:
<?php
protected function createComponentSearchForm()
{
$categoryList = $this->offerCategory->findAll()->fetchPairs('id', 'title');
$form = new Form();
$form->addText('text', 'Co:')
->setAttribute('placeholder', 'Hledaný text...');
$form->addSelect('category_id', 'Zobrazit jen:', $categoryList)
->setPrompt('Vše');
$form->addButton('search', 'Vyhledat');
$form->onSuccess[] = $this->searchOfferSubmitted;
return $form;
}
?>
Vykresleni pomoci snippet:
<?php
{snippet offers}
{if count($offers) > 0}
{foreach $offers as $offer}
<div n:snippet="item-{$offer->id}" class="post-offer">
<?php $count = 0; ?>
{foreach $offer->related('offer_photos') as $photo}
{if $count == 0}
<img src="{$basePath}/{$photo->photo->filepath_min}" alt="{$photo->photo->title}" title="{$photo->photo->title}" />
<?php $count++; ?>
{/if}
{/foreach}
<h3><a href="{link Offer:detail $offer->id}">{$offer->title}</a></h3>
<article class="offer-description">
{$offer->description|noescape}
</article>
<a href="{link Offer:detail $offer->id}" class="view-detail">Detail</a>
<div class="cleaner"> </div>
</div>
{/foreach}
{else}
<p>Aktuálně je naše nabídka prázdná!</p>
{/if}
{/snippet}
?>
Po kliknutí na tlačítko se zavolá:
<script>
jQuery(window).ready(function() {
$('#frm-searchForm-search').click(function() {
var value = $('#frm-searchForm-text').val();
$.nette.ajax({
'url': '?do=search',
'data': {
term: value
}
});
});
</script>
Kde se volá tento handle:
<?php
public function handleSearch($term) {
$this->template->offers = $this->offer->findBy(array('id' => 7));
$this->redrawControl('offers');
}
?>
Když si zobrazím co se mi po odeslání formuláře vrátí, skutečně se vrací v $offers pouze ten jeden produkt, ale v šabloně na stránce stále vidím všechny jako na začátku.
Jak prosím zařídit, aby se mi výpis překreslil a byly skutečně vidět jen produkty, které vrátí handle?
- Oli
- Člen | 1215
Nevím jestli to na to může mít vliv, zkus ale misto
$.nette.ajax({
'url': '?do=search',
'data': {
term: value
}
});
toto
$.nette.ajax({
'url': {link search!},
'data': {
term: value
}
});
Ještě se ujisti, že nemáš nikde v presenteru žádný dump, s tím to nejde. Jinak to na první pohled vypadá funkčně.
- Tomáš Votruba
- Moderator | 1114
Něco podobného jsem řešil již dávno, tak si nejsem jist. Nicméně si zkus definovat proměnnou, kterou budeš plnit a do šablony ji předáš pouze jednou.
Pokud by toto nešlo, zkus jestli ti jde pouhá invalidace po ajaxovém odkazu, případně prověřit připojené .js knihovny.
private $offerResult;
public function handleSearch($term)
{
$this->offerResult = 'search result: ' . $term;
$this->redrawControl('results');
}
public function renderIndex()
{
if ($this->offerResult == NULL) {
$this->offerResult = 'main result';
}
$this->template->offers = $this->offerResult;
}
- Filip023
- Člen | 13
Tomáš Votruba napsal(a):
Něco podobného jsem řešil již dávno, tak si nejsem jist. Nicméně si zkus definovat proměnnou, kterou budeš plnit a do šablony ji předáš pouze jednou.
Pokud by toto nešlo, zkus jestli ti jde pouhá invalidace po ajaxovém odkazu, případně prověřit připojené .js knihovny.
private $offerResult; public function handleSearch($term) { $this->offerResult = 'search result: ' . $term; $this->redrawControl('results'); } public function renderIndex() { if ($this->offerResult == NULL) { $this->offerResult = 'main result'; } $this->template->offers = $this->offerResult; }
Zkusil jsem upravit, ale stale končím se stejným problémem. V debugu vidím, že se mi opět vrátil jen jeden výsledek, ale stranka se nepřekreslí.
Aktuálně mám připojené tyto .js knihovny: jquery-1.11.0.min.js, nette.ajax.js
Pro tento příklad by měli stačit nebo je potřeba ještě nějaké další?
- Oli
- Člen | 1215
Melo by stacit. Zkus jeste (jen na zkousku) udelat neco jako:
private $pokus = 'ahoj';
public function renderDeafult()
{
$this->template->pokus = $this->pokus;
}
public function handlePokusHandler()
{
$this->pokus = 'nazdar';
$this->redrawControl('pokus');
}
<a class="ajax" n:href="pokusHandler!">pokusný odkaz</a>
{snippet pokus}
{$pokus}
{/snippet}
Asi mas napojeny to nette.ajax.js pomoci init();
? Jinak by to
asi hazelo nejakej js error…
- Filip023
- Člen | 13
Oli napsal(a):
Melo by stacit. Zkus jeste (jen na zkousku) udelat neco jako:
private $pokus = 'ahoj'; public function renderDeafult() { $this->template->pokus = $this->pokus; } public function handlePokusHandler() { $this->pokus = 'nazdar'; $this->redrawControl('pokus'); }
<a class="ajax" n:href="pokusHandler!">pokusný odkaz</a> {snippet pokus} {$pokus} {/snippet}
Asi mas napojeny to nette.ajax.js pomoci
init();
? Jinak by to asi hazelo nejakej js error…
Ano napojené to mám přes init();
Když jsem tohle zkusil, tak se mi text ahoj bez problémů překreslil na nazdar.
Každopádně stále netuším, jak vyřešit překreslení v nabídce.
- sKopheK
- Člen | 207
Pokud nemusíš používat vlastní js pro odesílání formuláře apod.,
tak prostě nastav formuláři class ajax
a
nette.ajax.js
by se měl postarat o zbytek. Odeslání formuláře
neobsluhuj v nějaké nezávislé metodě, ale v metodě přiřazené
formuláři. Nezapomeň zohlednit odeslání bez zapnutého JavaScriptu, kdy
hledaný parametr bude v URL – to bys měl obecně dělat vždy
jako první.
protected function createComponentSearchForm()
{
...
$form = new Form();
$form->getElementPrototype()->class('ajax');
...
$form->onSuccess[] = $this->searchOfferSubmitted;
return $form;
}
public function searchOfferSubmitted(Form $form)
{
$this->template->offers = $this->offer->findBy(array('id' => 7));
if ($this->isAjax())
{
$this->redrawControl('offers');
}
else
{
$this->redirect(...);
}
}
- Filip023
- Člen | 13
sKopheK napsal(a):
Pokud nemusíš používat vlastní js pro odesílání formuláře apod., tak prostě nastav formuláři class
ajax
anette.ajax.js
by se měl postarat o zbytek. Odeslání formuláře neobsluhuj v nějaké nezávislé metodě, ale v metodě přiřazené formuláři. Nezapomeň zohlednit odeslání bez zapnutého JavaScriptu, kdy hledaný parametr bude v URL – to bys měl obecně dělat vždy jako první.protected function createComponentSearchForm() { ... $form = new Form(); $form->getElementPrototype()->class('ajax'); ... $form->onSuccess[] = $this->searchOfferSubmitted; return $form; } public function searchOfferSubmitted(Form $form) { $this->template->offers = $this->offer->findBy(array('id' => 7)); if ($this->isAjax()) { $this->redrawControl('offers'); } else { $this->redirect(...); } }
Děkuji za radu, změnil jsem dle navodu, který píšeš. Ovšem jsem se
dostal do stejného problému jako předtím. Formulář se mi odešle přes
ajax, v debugu vidím, že se mi vrátil jen hledaný produkt, ale snippet se
nepřekreslí a stále zůstanou vypsány všechny nabídky.
Nenapadá ještě co bych mohl zkusit?
Editoval Filip023 (19. 4. 2014 8:45)