Livesearch pomocí Ajax v Nette

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

Zdravím,

našel jsem toto vlákno, které se tím zabývá, ale nějak to nemohu rozchodit.

Jde o to, že když přidám vše zmíněné od Vojty Dobeše
Homepage:

public function handleSearch($term)
{
    $this->template->results = $this->produkty->findAll()->where('nazev', $term);
    $this->redrawControl('results');
}

latte:

{snippet results}
{foreach $results as $result}
    ...
{/foreach}
{/snippet}

$('#{$control["searchForm"]['search']}').on('change input', function () {
    var value = $(this).val();
    if (value.length >= 2) {
        $.nette.ajax({
            'url': {link search!}
            'data': {
                term: value
            }
        });
    }
});

Tak už na mě laděnka řvě: Undefined variable: results

Na netu jsem vyštrachal toto přiřazení k tomu formuláři

$this->template->results = $this['searchForm'];

Takže od laděnky mám klid, ale pořád se nemohu dopídit toho, jak to zprovoznit…

Mohl by mi prosím někdo poradit?

Editoval wicked (13. 1. 2015 10:24)

Etch
Člen | 403
+
0
-
$this->template->results = $this['searchForm'];

Proč by v results měl být formulář?? V results by měl být defaultně prázdný array popřípadě by se v šabloně mělo kontrolovat jestli je daná proměná nadefinovaná. Tedy buď:

$this->template->results = array();

nebo

{snippet results}
	{ifSet $results}
		{foreach $results as $result}
    		...
		{/foreach}
	{/ifSet}
{/snippet}

V JS máš pak podle mě špatně selector, protože ač si tím nejsem jistý, tak si myslím, že {$control["searchForm"]['search']} nevrací ID prvku, ale mělo by tam být něco jako:

$('#{$control["searchForm"]['search']->htmlId}').on('change input', function () {
    var value = $(this).val();
    if (value.length >= 2) {
        $.nette.ajax({
            'url': {link search!}
            'data': {
                term: value
            }
        });
    }
});

Navíc si stejně myslím, že daný selector by měl být udělaný obecněji a neměl by využívat konstrukce typu „#$control[…]“, protože si tím naprosto zazdíš možnost tento JS přesunout do externího souboru a tedy i variantu, kdy JS načítáš na konci <body>.

Editoval Etch (13. 1. 2015 10:46)

wicked
Člen | 290
+
0
-

Tak jsem to upravil podle Tebe, tedy:

$this->template->results = array();

a script

<script>
    $(function () {
    $('#{$control["searchForm"]['search']->htmlId}').on('change input', function () {
    var value = $(this).val();
            if (value.length >= 2) {
    $.nette.ajax({
    'url': {link search!}
    'data': {
    term: value
    }
    });
    }
    });
    });
</script>

A vypisovat to chci takto:

{snippet results}
        <div id="naseptavac">
            <table class="wp-nap">

                <tr n:foreach="$results as $item">
                    <td class="nasp-img"><img src="{$item->nazev}"></td>
                    {*<td class="nasp-nazev">{$item->nazev}</td>
                    <td class="nasp-cena">{$item->cena_dph}/td>
                    <td class="nasp-zob"><a href="#"><button>zobrazit</button></a></td>*}
                </tr>

            </table>
        </div>
    {/snippet}

Jenže mě to pořád nic nevrací …nic se neprovede …

Mimochodem když kouknu na zdrojak aplikace, tak není toto divné?
je to v tom JS

'url': "\/cyklozbozi\/www\/?do=search"

Editoval wicked (13. 1. 2015 11:09)

Etch
Člen | 403
+
0
-

Naváže se opravdu event na daný input? Zjistit se to dá jednoduše následujícím JS:

<script>
$(function(){
	$('#{$control["searchForm"]['search']->htmlId}').on('change input', function () {
		alert(1);
    });
});
</script>

Provede se vůbec ten ajax request a vrátí potřebná data?? Nejlépe to můžeš zjistit ve firebugu.

wicked
Člen | 290
+
0
-

Ve firebugu jsem to zkoušel najít, ale nějak bez úspěchu, pořádně se v tom nevyznám…

Zkusím to upravit podle tebe, uvidíme

wicked
Člen | 290
+
0
-

Aha … tak to nic nedělá …

wicked
Člen | 290
+
0
-

Ale ID toho inputu má ten JS správně …

<input type="text" name="search" placeholder="Přehazovačka, koutoučové brzdy, horské kolo ..." id="frm-searchForm-search" required data-nette-rules='[{"op":":filled","msg":"Pole mus\u00ed b\u00fdt vypln\u011bno!"}]'></td>

script jsem upravil takto, již to reaguje:

<script>
$(function(){
    $('#frm-searchForm-search').on('change input', function () {
        alert(1);
    });
});
</script>

Editoval wicked (13. 1. 2015 15:52)

David Matějka
Moderator | 6445
+
0
-

@wicked a nebylo to nejak escapovany?
Spravne bys to mel vypisovat asi takhle:

$('#' + {$control["searchForm"]['search']->htmlId})
wicked
Člen | 290
+
0
-

Jenže když tedy upravím ten script na toto:

<script>
    $(function () {
    $('#frm-searchForm-search').on('change input', function () {
    var value = $(this).val();
            if (value.length >= 2) {
    $.nette.ajax({
    'url': {link search!}
    'data': {
    term: value
    }
    });
    }
    });
    });
</script>

Stále se nic neděje, jak to mohu v tom firebugu odchytnout? Respektivě není ještě divná ta cesna v tom url?

'url': "\/cyklozbozi\/www\/?do=search"
wicked
Člen | 290
+
0
-

matej21 napsal(a):

@wicked a nebylo to nejak escapovany?
Spravne bys to mel vypisovat asi takhle:

$('#' + {$control["searchForm"]['search']->htmlId})

Ano, i takto to funguje :)

Každopádně co tam je ještě špatně? že se nic neděje? Respektivě jak to ochdytit v tom firebugu? když tam nastavím ten ajax

<script>
$(function(){
    $('#' + "frm-searchForm-search").on('change input', function () {
        var value = $(this).val();
    if (value.length >= 2) {
        $.nette.ajax({
            'url': "\/cyklozbozi\/www\/?do=search" // tohle mě uděla {link search}
            'data': {
                term: value
            }
        });
    }
    });
});
</script>

Tak se nic němění …

Etch
Člen | 403
+
0
-

Nic se neděje znamená co? Neproběhne ajax request nebo se nepřekreslí snippet?

JS si tam dej následující. Tam by měla být na 100% jistota, že se to na daný input chytne, pokud má opravdu id „#frm-searchForm-search“

<script>
    $(function () {
	    $('#frm-searchForm-search').on('change', function () {
    		var value = $(this).val();
            if (value.length >= 2) {
			    $.nette.ajax({
			    'url': {link search!}
			    'data': {
				    term: value
				    }
			    });
		    }
	    });
    });
</script>
wicked
Člen | 290
+
0
-

Mám to teď takto:

default.latte

<script>
    $(function () {
        $('#frm-searchForm-search').on('change', function () {
            var value = $(this).val();
            if (value.length >= 2) {
                $.nette.ajax({
                'url': {link search!}
                'data': {
                    term: value
                    }
                });
            }
        });
    });
</script>

{snippet results}
        <div id="naseptavac">
            <table class="wp-nap">

                <tr n:foreach="$results as $item">
                    <td class="nasp-img"><img src="{$item->nazev}"></td>
                </tr>

            </table>
        </div>
    {/snippet}

Presenter:

 public function handleSearch($term) {
        $this->template->results = $this->produkty->findAll()->where('nazev', $term);
        $this->redrawControl('results');
    }

public function renderDefault() {
        $this->template->results = array();
    }

public function createComponentSearchForm() {
        $form = new Form();
        // Vyhledavaci pole
        $form->addText('search', '')
                ->setRequired('Pole musí být vyplněno!')
                ->setAttribute('placeholder', 'Přehazovačka, koutoučové brzdy, horské kolo ...')
                ->getControlPrototype();
        // Vyber typu
        $form->addSelect('typ', '', array(
            'bazarove' => 'Bazarové',
            'nove' => 'Nové',
            'oboji' => 'Bazarové i nové'
        ))->setPrompt('Typ zboží ...');
        // Odesilaci tlacitko
        $form->addSubmit('send', 'Hledat zboží')
                ->getControlPrototype()
                ->class('btn btn-info');
        // Zavolame metodu searchBoxSuccedded po uspesnem odeslani
        $form->onSuccess[] = $this->searchBoxSuccedded;
        return $form;
    }

Ale když začnu psát do pole, tak se snipet vubec neprekresluje, nic to nevypisuje …

David Matějka
Moderator | 6445
+
0
-

handle se vola pred render. A v render nastavujes results na array()

wicked
Člen | 290
+
0
-

matej21 napsal(a):

handle se vola pred render. A v render nastavujes results na array()

jenže když v render neuvedu results tak to na me rve, ze neni definovano $results … tak na co to mám nastavit tedy?

wicked
Člen | 290
+
0
-

wicked napsal(a):

matej21 napsal(a):

handle se vola pred render. A v render nastavujes results na array()

jenže když v render neuvedu results tak to na me rve, ze neni definovano $results … tak na co to mám nastavit tedy?

Odstanil jsem render z preenteru a do sablony pridal {ifset $results} za {snippet} takto:

{snippet results}
        {ifset $results}
            <div id="naseptavac">
                <table class="wp-nap">

                    <tr n:foreach="$results as $item">
                        <td class="nasp-img"><img src="{$item->nazev}"></td>
                        <td class="nasp-nazev">{$item->nazev}</td>
                        <td class="nasp-cena">{$item->cena_dph}/td>
                        <td class="nasp-zob"><a href="#"><button>zobrazit</button></a></td>
                    </tr>

                </table>
            </div>
        {/ifset}
    {/snippet}

Ale stále se mi nic nevykresluje … snazim se v tom firebugu najit jak si overit zda to neco posila nebo ne, ale take marne …

Etch
Člen | 403
+
0
-

Zjisti si něco o životním cyklu presenteru.

public function actionDefault(){
	$this->template->results = array();
}

Ve firebugu to je vidět v záložce „konzole“.

Editoval Etch (13. 1. 2015 17:38)

wicked
Člen | 290
+
0
-

Etch napsal(a):

Zjisti si něco o životním cyklu presenteru.

public function actionDefault(){
	$this->template->results = array();
}

Ve firebugu to je vidět v záložce „konzole“.

Tak v debugeru jedine co je tak bylo
**SyntaxError: missing } after property list

‚data‘: {**

pridal jsem do scriptu „,“ takze :

<script>
    $(function () {
        $('#frm-searchForm-search').on('change', function () {
            var value = $(this).val();
            if (value.length >= 2) {
                $.nette.ajax({
                'url': {link search!},
                'data': {
                    term: value,
                    }
                });
            }
        });
    });
</script>

A ted v konzoli vidim akorad:

Error: Bootstrap's JavaScript requires jQuery


...(typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requi...


bootstrap.js (line 7, col 43)
ReferenceError: jQuery is not defined


}(window, document, jQuery));

fancybox.js (řádek 2018)
ReferenceError: $ is not defined


$(function () {

main.js (řádek 1)
"NetworkError: 500 Internal Server Error - http://aitee.savana-hosting.cz/cyklozbozi/www/css/open-sans/OpenSans-Light.ttf"
OpenSan...ght.ttf
"NetworkError: 500 Internal Server Error - http://aitee.savana-hosting.cz/cyklozbozi/www/css/open-sans/OpenSans-Bold.ttf"
OpenSans-Bold.ttf
"NetworkError: 500 Internal Server Error - http://aitee.savana-hosting.cz/cyklozbozi/www/css/open-sans/OpenSans-Regular.ttf"
OpenSan...lar.ttf
"NetworkError: 500 Internal Server Error - http://aitee.savana-hosting.cz/cyklozbozi/www/css/open-sans/OpenSans-BoldItalic.ttf"
OpenSan...lic.ttf
"NetworkError: 500 Internal Server Error - http://aitee.savana-hosting.cz/cyklozbozi/www/css/open-sans/OpenSans-Semibold.ttf"
OpenSan...old.ttf

Já už fakt nevím …

tady je ještě ten main.js

$(function () {
    $.nette.init();
});

$(document).ready(function () {
    $(".fancybox").fancybox({
        openEffect: "none",
        closeEffect: "none"
    });
});

function dotaz() {
    if (window.confirm("Opravdu si přejete provést tuto akci?"))
    {
        return true;
    }
    else
        return false;
};

Editoval wicked (13. 1. 2015 17:48)

Etch
Člen | 403
+
0
-

Nenatahuje se ti jQuery a nebo se natahuje pozdě. Kde přesně a co všechno v layoutu natahuješ za JS.

wicked
Člen | 290
+
0
-

Všechno v @layout.latte v <head>

<script src="{$basePath}/js/bootstrap.js"></script>
<script src="{$basePath}/js/fancybox.js"></script>
<script src="{$basePath}/js/main.js"></script>
<script src="{$basePath}/js/netteForms.js"></script>
<script src="{$basePath}/js/jquery-2.1.1.js"></script>
<script src="{$basePath}/js/nette.ajax.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
{include #header}

a pak v default.latte

{block header}
<script>
    $(function () {
        $('#frm-searchForm-search').on('change', function () {
            var value = $(this).val();
            if (value.length >= 2) {
                $.nette.ajax({
                'url': {link search!},
                'data': {
                    term: value,
                    }
                });
            }
        });
    });
</script>
{/block}

Všechny linky samozdřejmně funkční

Etch
Člen | 403
+
0
-
<script src="{$basePath}/js/jquery-2.1.1.js"></script>

přesuň na první pozici

wicked
Člen | 290
+
0
-

Přesunuto, chyby opraveny (ty chybějící fonty)…

teď když reload webu, konzole je prázdná .. začnu psát to inputu z formu a nic se neděje v konzoli nic, a v sablone se take nic nevykresli …

Etch
Člen | 403
+
0
-

Jen taková úplně blbá otázka, ale pro jistotu se zeptám… Opravdu víš, kdy se volá „change“ event?? Víš, že change se volá až při „defocusu“ z inputu…

wicked
Člen | 290
+
0
-

Přiznám se uplně bez mučení jquery je pro mě španělská vesnice …

Tento script jsem našel zde v jednom vlákně a psal ho @vojtech.dobes tak jsem jej chtěl použít … hlavně mě moc nekamenuj …

Mysteria
Člen | 797
+
0
-

Vidíš a hned pod ním je napsáno, že se kromě change musí přidat ještě keyup událost, aby to fungovalo tak jak si představuješ.

wicked
Člen | 290
+
0
-

wicked napsal(a):

Přiznám se uplně bez mučení jquery je pro mě španělská vesnice …

Tento script jsem našel zde v jednom vlákně a psal ho @vojtech.dobes tak jsem jej chtěl použít … hlavně mě moc nekamenuj …

Přepsal jsem to na keyup místo on a konecne v konzili mám

GET http://aitee.savana-hosting.cz/cyklozbozi/www/?do=search&term=as

200 OK
		318ms
jquery-2.1.1.js (řádek 8623)
ParametryHlavičkyOdezvaJSONCookies

{"state":[],"snippets":{"snippet--results":"        <div id=\"naseptavac\">\n            <table class=\"wp-nap\">\n\n\n            <\/table>\n        <\/div>\n"}}

Ale stále se mi nic ve snippetu, respektivě v tom kodu kde mám foreach (viz víše) nic neděje …

wicked
Člen | 290
+
0
-

Omlouvá se, teď už je to moje blbost … samoždřejmně mě to ted vypíše ale pouze pokud zadám přesný název do vyhledávání musím upravit sql aby to bralo jen část (předpokládám like :) )

EDIT: ne ted, ale porád je to moje blbost ;)

DĚKUJI VŠEM ZA POMOC!

Takto jsem ještě upravil handle:

public function handleSearch($term) {
        $this->template->results = $this->produkty->findAll()->where('nazev LIKE ?', '%'.$term.'%');
        $this->redrawControl('results');
    }

Editoval wicked (13. 1. 2015 18:52)

Etch
Člen | 403
+
0
-

OT: No měl by sis tam upravit více věcí… například includování neexistujícího bloku „header“ nebo smyčku v přesměrování v „admin“ sekci…

wicked
Člen | 290
+
0
-

Etch napsal(a):

OT: No měl by sis tam upravit více věcí… například includování neexistujícího bloku „header“ nebo smyčku v přesměrování v „admin“ sekci…

O té smičce vím :) zatím řeším jiné věci :)

A ohledně toho includování .. v layoutu mam {include #header} a v potom v sablonach vzdy {block header}{/block} to je něco špatně?

Etch
Člen | 403
+
0
-

No špatně je na tom to, že ne všude máš ten block opravdu definovanej.

wicked
Člen | 290
+
0
-

Etch napsal(a):

No špatně je na tom to, že ne všude máš ten block opravdu definovanej.

jojo to vím, neboj, je to celé ve vývoji :) Ale děkuji :)

wicked
Člen | 290
+
0
-

Ještě se zeptám na poslední otázku …

Tahle když začnu psát, tak to nachází a funguje ok, ale jakmile smažu kompletně řádek, zůstane tam ‚viset‘ poslední shoda v zaznamu … jde docili aby kdyz tam neni nic vyplněno, tak aby se to ten snippet nezobrazil?

Etch
Člen | 403
+
0
-

Mnoha způsoby… nejjednodušší je například:

<script>
    $(function () {
        $('#frm-searchForm-search').on('keyup', function () {
            var value = $(this).val();
            if (value.length >= 2) {
                $.nette.ajax({
                'url': {link search!},
                'data': {
                    term: value,
                    }
                });
            }else{
				$('div#naseptavac').hide();
			}
        });
    });
</script>

Editoval Etch (13. 1. 2015 22:11)