Ajax do handle na vybrání hodnoty ze selectu

unjustolaf
Člen | 29
+
0
-

Zdravim borci,

Snažím se vytvořit select pod produktem v mém e-shopu kde by bylo rúzné množství daného produktu a ve chvíli kdy uživatel vybere nějakou hodnotu z tohoto selectu nastane handle který tuto vybranou hodnotu uloží do proměnné a ta se potom uloží do šablony odkud jí mohu poslat jako parametr. Nechci aby uživatel musel klikat na tlačítko a tím potvrzoval dané množství produktu a proto jsem se rozhodl poprvé v mém životě na něco použít ajax.

Postupoval jsem následovně.

  1. Stáhl jsem si soubor nette.ajax.js z tohoto githubu
  2. Tento soubor jsem si nahrál do složky www/js/
  3. Do @layout.latte jsem dal odkaz
<?php
<body>

<header>
    {include "Components/header.latte"}
</header>

<div n:foreach="$flashes as $flash" class="flash-{$flash->type}">{$flash->message}</div>

{include content}

<footer>
    {include "Components/footer.latte"}
</footer>
{block scripts}
	<script src="http://code.jquery.com/jquery-3.3.1.slim.js" integrity="sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=" crossorigin="anonymous"></script>
	<script src="{$basePath}/js/nette.ajax.js"></script> //viz zde
	<script src="{$basePath}/bootstrap/js/bootstrap.min.js"></script>
	<script src="{$basePath}/js/main.js"></script>
	<script src="https://nette.github.io/resources/js/netteForms.min.js"></script>
{/block}
</body>
</html>
?>
  1. Do main.js jsem dal následující kód (vše podle návodu na githubu)
<?php
$(function () {
    $.nette.init();
});
?>
  1. V této fázi jsem si myslel že mám ajax úspěšně naimplementovaný a začel jsem zkoušet vlákna jako je např. toto Ale nic nefungovalo a vždy když jsem vybral hodnotu ve svém selectu žádný ajax nenastal. Po 5 hodinách jsem už vyzkoušel všechny vlákna zde na fóru ve kterých se jedná o onChange selectu a nic mi nefungovalo, žádný ajax nikdy nenastal a nikdy jsem se nedostal do handle který jsem si vytvořil. Teď už jsem tak zoufalý, že píši sem a žádám vás o pomoc.

Nyní jsem kompletně vyčistil všechny mé pokusy a mám čistý kód do kterého bych chtěl tento ajax implementovat. Jsem tedy za 4. krokem (viz výše) a mám toto:

item.latte

<?php
{block content}
...
<form n:name="selectAmount" method="GET">
     <select n:name="amount" class="form-control">
     </select>
</form>
...
<style>
// Zde potřebuji fungující ajax, který pozná když uživatel vybere nějakou možnost ze selectu se jménem amount a pošle jeho hodnotu do mého handleSelectAmount(), kde s ní budu dále pracovat
</style>
?>

ShopPresenter.php

<?php
	protected function createComponentSelectAmount()
    {
        $form = new Form;

        $form->addSelect('amount', 'Vyberte množství:', [
            '1' => '10g',
            '2' => '50g',
            '3' => '100g',
        ])->setDefaultValue('1');

        $form->onSuccess[] = [$this, 'selectAmountSuccess'];

        return $form;
    }


    public function selectAmountSuccess(Form $form)
    {

    }

    public function handleRefresh($value){
        //zde bych chtěl obdržet value selectu po jejím vybrání uživatele
    }
?>

Prosím poraďte mi jak na to, jsem už zoufalý. Vždy se snažím vše vymyslet sám ale tentokrát už opravdu nevím co dál.

Předem všem děkuji

japlavaren
Člen | 404
+
0
-

dovod preco ti to nefunguje je, ze aby sa zavolalo ajaxove volanie musi ho nieco spustit. ajax plugin ktory pouzivas ma na to triedy ktorymi oznacis co ma byt ajaxove: https://github.com/…tte.ajax.js/#…

to co chces ty bude vyzadovat obsluzny js kod. tak ako to mas navrhnute potrebujrd toto:
na tym selectboxom sledovat udalost change a pri change zavolat rucne jQuery.ajax call na url tvojho handle
nieco ako:

<script>
$(function(){
	$.nette.init();

	$('#{$form[amount]->htmlId}').change(function() {
		$.ajax({
			method: 'get',
			url: {link refresh!},
			data: {value: $(this).val()}
		});
	});
});
</script>

takto nejak by ti to mohlo fungovat

unjustolaf
Člen | 29
+
0
-

japlavaren napsal(a):

dovod preco ti to nefunguje je, ze aby sa zavolalo ajaxove volanie musi ho nieco spustit. ajax plugin ktory pouzivas ma na to triedy ktorymi oznacis co ma byt ajaxove: https://github.com/…tte.ajax.js/#…

to co chces ty bude vyzadovat obsluzny js kod. tak ako to mas navrhnute potrebujrd toto:
na tym selectboxom sledovat udalost change a pri change zavolat rucne jQuery.ajax call na url tvojho handle
nieco ako:

<script>
$(function(){
	$.nette.init();

	$('#{$form[amount]->htmlId}').change(function() {
		$.ajax({
			method: 'get',
			url: {link refresh!},
			data: {value: $(this).val()}
		});
	});
});
</script>

takto nejak by ti to mohlo fungovat

Píše mi to unknown macro {value} a podtrhava radek data: {value: $(this).val()} nemá to náhodou být {‚value‘: $(this).val()}?

A ještě se chci zeptat, když bych chtěl otestovat jestli mi do handleRefresh prišla ta hodnota value a udělám to takto:

<?php
public function handleRefresh($value)
{
    dump($value);
    die();
}
?>

Tak se po vybrání hodnoty ze selectboxu absolutně nic nestane takže ten ajax bud furt nefunguje nebo jsem z toho uz fakt jelen.

GEpic
Člen | 566
+
0
-

zapiš to takto (ano, s tou mezerou, ať se to nevyhodnocuje jako latte zápis):

{ value: $(this).val() }

Editoval GEpic (29. 8. 2018 23:22)

unjustolaf
Člen | 29
+
0
-

GEpic napsal(a):

zapiš to takto (ano, s tou mezerou, ať se to nevyhodnocuje jako latte zápis):

{ value: $(this).val() }

Provedl jsem, ale handle Refresh se stále nevykoná

<?php
public function handleRefresh($value)
{
    dump($value);
    die();
}
?>

Možná to takhle nelze, pokud něco dělám špatně upozorněte mě prosím, ale takhle ja vypisuji promene v metodach odjakziva.

Mistrfilda
Člen | 76
+
0
-

Ahoj,

v situaci kdy se má volat handle, je dole v tracy debug baru vidět ajax panel (jestli tedy používáš novou verzi nette, 2 panely nad sebou – tracy a ajax)? Jinak zkus místo dump a die použít bdump a kouknout jestli něco nevypíše do ajax debug baru dole.

unjustolaf
Člen | 29
+
0
-

Mistrfilda napsal(a):

Ahoj,

v situaci kdy se má volat handle, je dole v tracy debug baru vidět ajax panel (jestli tedy používáš novou verzi nette, 2 panely nad sebou – tracy a ajax)? Jinak zkus místo dump a die použít bdump a kouknout jestli něco nevypíše do ajax debug baru dole.

Ahoj, tak nad tracy debug barem nemám žádný ajax panel to za prvé a verzi nette bych měl mít aktuální, tedy pokud stačí přepsat verzi nette v composer.json a v terminalu dat composer update ve slozce projektu. Bdump jsem zkoušel bez úspěchu, nemyslím si, že se handleRefresh vubec zavolá, ajax podle mě nic nědělá.

Mistrfilda
Člen | 76
+
0
-

Zkus dát do jakkékoliv šablony presenteru

<a class="ajax" n:href="test!">KLIK</a>

a do presenteru

public function handleTest()
{
	bdump("AJAX call");
}

Jestli toto nefunguje tak bude problém s načítaním nette.ajax knihovny, kde teď voláš $.nette.init()? Prohlizecova console zadne chybi nehlasi?

unjustolaf
Člen | 29
+
0
-

Mistrfilda napsal(a):

Zkus dát do jakkékoliv šablony presenteru

<a class="ajax" n:href="test!">KLIK</a>

a do presenteru

public function handleTest()
{
	bdump("AJAX call");
}

Jestli toto nefunguje tak bude problém s načítaním nette.ajax knihovny, kde teď voláš $.nette.init()? Prohlizecova console zadne chybi nehlasi?

Toto mi vyhodí klasický dump s textem „AJAX call“.

To je zvláštní jsem si jistý že do prohlížečové konzole jsem se předtím koukal a nic tam nebylo – teď tam je:

  1. TypeError: $.ajax is not a function – a když ho rozkliknu

    localhost:8888/e-shop/e-shop/www/js/nette.ajax.js:225:25

    requestHandler

    localhost:8888/e-shop/e-shop/www/js/nette.ajax.js:48:14

    dispatch

    code.jquery.com/jquery-3.3.1.slim.js:5182:16

    add/elemData.handle

    code.jquery.com/jquery-3.3.1.slim.js:4991:6

  2. ReferenceError: $ is not defined.

Editoval unjustolaf (30. 8. 2018 1:27)

Mistrfilda
Člen | 76
+
0
-

Dobře, tím pádem je nette.ajax načteno a mělo by fungovat jestli funguje příklad co jsem poslal. Dej sem prosím část latte souboru kde se snažíš ajax volat, obalujes ještě dané scipty do blocku?

unjustolaf
Člen | 29
+
0
-

Celé moje latte:

<?php
{block content}
<div class="container">
    <div class="row mt-5">
        <div class="col-lg-9">
            <div class="card">
                <img style="width: auto; height: auto" class="card-img-top img-fluid" src="{$basePath}/{$item->item_image}" alt="">
                <div class="card-body">
                    <h3 class="card-title">{$item->item_name}</h3>
                    <h4 style="color: red">{$item->item_price},- Kč</h4>
                    <p class="card-text">{$item->item_content}</p>
                    {if $item->item_evaluation == NULL}
                        <span class="text-muted"><i class="far fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i></span>
                    {elseif $item->item_evaluation < 0.5}
                        <span class="text-muted"><i class="far fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i></span>
                    {elseif $item->item_evaluation >= 0.5 && $item->item_evaluation < 1}
                        <span class="text-muted"><i class="fas fa-star-half"></i></span>
                    {elseif $item->item_evaluation >= 1 && $item->item_evaluation < 1.5}
                        <span class="text-muted"><i class="fas fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i></span>
                    {elseif $item->item_evaluation >= 1.5 && $item->item_evaluation < 2}
                        <span class="text-muted"><i class="fas fa-star"></i><i class="fas fa-star-half"></i></span>
                    {elseif $item->item_evaluation >= 2 && $item->item_evaluation < 2.5}
                        <span class="text-muted"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i></span>
                    {elseif $item->item_evaluation >= 2.5 && $item->item_evaluation < 3}
                        <span class="text-muted"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star-half"></i></span>
                    {elseif $item->item_evaluation >= 3 && $item->item_evaluation < 3.5}
                        <span class="text-muted"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="far fa-star"></i><i class="far fa-star"></i></span>
                    {elseif $item->item_evaluation >= 3.5 && $item->item_evaluation < 4}
                        <span class="text-muted"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star-half"></i></span>
                    {elseif $item->item_evaluation >= 4 && $item->item_evaluation < 4.5}
                        <span class="text-muted"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="far fa-star"></i></span>
                    {elseif $item->item_evaluation >= 4.5 && $item->item_evaluation < 5}
                        <span class="text-muted"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star-half"></i></span>
                    {elseif $item->item_evaluation == 5}
                        <span class="text-muted"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i></span>
                    {/if}
                    {if $item->item_evaluation == NULL}
                        <span>Doposud nebylo přidáno žádné hodnocení produktu</span>
                    {elseif $item->item_evaluation <= 0.5}
                        <span> {$item->item_evaluation} hvězdiček</span>
                    {elseif $item->item_evaluation >= 0.5 && $item->item_evaluation < 1}
                        <span> {$item->item_evaluation} hvězdičky</span>
                    {elseif $item->item_evaluation >= 1 && $item->item_evaluation < 1.5}
                        <span> {$item->item_evaluation} hvězdička</span>
                    {elseif $item->item_evaluation >= 1.5 && $item->item_evaluation < 2}
                        <span> {$item->item_evaluation} hvězdiček</span>
                    {elseif $item->item_evaluation >= 2 && $item->item_evaluation < 2.5}
                        <span> {$item->item_evaluation} hvězdičky</span>
                    {elseif $item->item_evaluation >= 2.5 && $item->item_evaluation < 3}
                        <span> {$item->item_evaluation} hvězdiček</span>
                    {elseif $item->item_evaluation >= 3 && $item->item_evaluation < 3.5}
                        <span> {$item->item_evaluation} hvězdičky</span>
                    {elseif $item->item_evaluation >= 3.5 && $item->item_evaluation < 4}
                        <span> {$item->item_evaluation} hvězdiček</span>
                    {elseif $item->item_evaluation >= 4 && $item->item_evaluation < 4.5}
                        <span> {$item->item_evaluation} hvězdičky</span>
                    {elseif $item->item_evaluation >= 4.5 && $item->item_evaluation < 5}
                        <span> {$item->item_evaluation} hvězdiček</span>
                    {elseif $item->item_evaluation == 5}
                        <span> {$item->item_evaluation} hvězdiček</span>
                    {/if}

                    <form n:name="selectAmount" class="ajax" method="GET">
                        <select n:name="amount" class="form-control">
                        </select>
                    </form>

                    <a class="ajax" n:href="test!">KLIK</a>

                    <div class="mt-3">
                        <a n:href="addToCart!, 'itemid' => $item->item_id, 'categoryid' => $item->category_id" style="color: white; background-color: red" class="btn btn-lg">
                            <i class="fas fa-cart-plus"></i> Přidat do košíku
                        </a>
                    </div>
                </div>
            </div>

            <div class="card card-outline-secondary my-4">
                <div class="card-header">
                    Recenze produktu
                </div>
                <div class="card-body">
                    {foreach $reviews as $review}
                        {if $review['review']->review_content == NULL}
                            <p style="color: #8c8c8c">Bez podrobnějšího hodnocení.</p>
                        {else}
                            <p>{$review['review']->review_content}</p>
                        {/if}
                        {if $review['review']->item_evaluation == 1}
                            <big class="text-muted">★ ☆ ☆ ☆ ☆</big><br>
                        {elseif $review['review']->item_evaluation == 2}
                            <big class="text-muted">★ ★ ☆ ☆ ☆</big><br>
                        {elseif $review['review']->item_evaluation == 3}
                            <big class="text-muted">★ ★ ★ ☆ ☆</big><br>
                        {elseif $review['review']->item_evaluation == 4}
                            <big class="text-muted">★ ★ ★ ★ ☆</big><br>
                        {else}
                            <big class="text-muted">★ ★ ★ ★ ★</big><br>
                        {/if}
                        <small class="text-muted">Hodnocení přidal <span style="color: blue">{$review['review']->review_author_name}</span> {$review['review']->date_created}</small>
                        <hr>
                    {/foreach}
                    {if $user_review == NULL}
                        <a n:href="Shop:addReview, 'itemid' => $item->item_id, 'categoryid' => $item->category_id" class="btn btn-success">Zanechat recenzi</a>
                    {elseif $user_review == "notLoggedIn"}
                        <a class="btn btn-warning">Na přidání recenze se musíte přihlásit</a><br><br>
                        <a class="btn btn-success" n:href="Sign:in">Přihlásit se nyní</a>
                    {else}
                        <a class="btn btn-warning">Už jste ponechal recenzi na toto zboží</a>
                    {/if}
                </div>
            </div>
            <div class="row">
                <div class="col-lg-12">
                    <div class="box">
                        <div class="box-icon">
                            <span><i class="fas fa-briefcase-medical fa-3x"></i></span>
                        </div>
                        <div class="info">
                            <p class="text-center">Výrobek není určen pro lidskou konzumaci. Výrobek je určen pouze pro vzdělávací/výzkumné účely.</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    $(function(){
        $.nette.init();
        $('#{$form[amount]->htmlId}').change(function() {
            $.ajax({
                method: 'get',
                url: {link refresh!},
                data: { value: $(this).val() }
            });
        });
    });
</script>
?>
Mistrfilda
Člen | 76
+
0
-

Zkus ukončít {block content} za posledním divem

		</div>
    </div>
</div>
{/block}

a script část obalit do

{block scripts}
	{include parent}
	<script>
    $(function(){
        $.nette.init();
        $('#{$form[amount]->htmlId}').change(function() {
            $.ajax({
                method: 'get',
                url: {link refresh!},
                data: { value: $(this).val() }
            });
        });
    });
	</script>
{/block}
unjustolaf
Člen | 29
+
0
-

Mistrfilda napsal(a):

Zkus ukončít {block content} za posledním divem

		</div>
    </div>
</div>
{/block}

a script část obalit do

{block scripts}
	{include parent}
	<script>
    $(function(){
        $.nette.init();
        $('#{$form[amount]->htmlId}').change(function() {
            $.ajax({
                method: 'get',
                url: {link refresh!},
                data: { value: $(this).val() }
            });
        });
    });
	</script>
{/block}

Hmm tohle něco udělalo, ted kdyz nactu stránku vyhodí se mi error Undefined variable: form na řádku $(‚#{$form[amount]->htmlId}‘).change(function() { a v konzoli SyntaxError: invalid increment/decrement operand.

Mistrfilda
Člen | 76
+
0
-

Jo sorry, moje chyba, dej prosím id selectu natvrdo přes

<select n:name="amount" id="selectid" class="form-control">

a pak změnit řádek ve scriptu z

$('#{$form[amount]->htmlId}').change(function() {

na

$('#selectid').change(function() {

Editoval Mistrfilda (30. 8. 2018 2:06)

unjustolaf
Člen | 29
+
0
-

Mistrfilda napsal(a):

Jo sorry, moje chyba, dej prosím id selectu natvrdo přes

<select n:name="amount" id="selectid" class="form-control">

a pak změnit řádek ve scriptu z

$('#{$form[amount]->htmlId}').change(function() {

na

$('#selectid').change(function() {

Proboha vůbec se neomlouvej, si můj zachránce. Ke stavu aplikace, tohle pomohlo, ted se dostanu na stranku bez erroru (i konzole je prazdna), ale kdyz kliknu na polozku v selectu napise mi to v konzoli TypeError: $.ajax is not a function

EDIT: Používal jsem slim verzi jquery která má smazané funkce jako např ajax takže stačilo prohodit verzi za uncompressed a ted uz si myslis vse funguje jak má

Editoval unjustolaf (30. 8. 2018 2:13)

unjustolaf
Člen | 29
+
0
-

No tak vše opravdu funguje jak má, teď už jen přemýšlím jaký způsob zvolit z handleRefresh abych si dostal tuto proměnou value zpět do template a podle ní vykreslil cenu ke zvolenému množství produktu.

Napadlo mě to dělat takhle i když vám se to asi bude zdát asi hloupé, mě v tuto chvíli nic jiného nenapadá.

<?php
	public function handleRefresh($value){
        $this->redirect("Shop:item", array("itemid" => $this->getParameter("itemid"), "amount" => $value));
    }
?>

Problém je že se žádný redirect nevykoná :(