Snippet + ajax vyhledávání

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Filip023
Člen | 13
+
0
-

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ě.

Oli
Člen | 1215
+
0
-

Protože životní cyklus presenteru. Ten render ti překreslí handle

Filip023
Člen | 13
+
0
-

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
+
0
-

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">&nbsp;</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
+
0
-

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ě.

Filip023
Člen | 13
+
0
-

Zkusil jsem změnit, ale chová se to stále stejně. V debugu vidím, že se mi vrátí jeden produkt jako výsledek, ale stránka se nepřekreslí.

V presenteru žádný dump nemám.

Tomáš Votruba
Moderator | 1114
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

sKopheK napsal(a):

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(...);
    }
}

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)