Ajax form odeslání a načtení dat

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

Dobrý den,
prosím nekamenujte mě za začátečnické dotazy, s ajaxem nějak furt začínám…
v šabloně mám dva formuláře, první formulář kosikRychleVlozeniForm, se ajaxově odesílá… přidá položky do košíku a do stránky se zboží přidá…
Nyní jsem chtěl, ještě u formuláře, který slouží pro aktualizaci položek v košíku, taky přenastavit na ajax, ale nejde mě to rozchodit. Nevím co dělám furt blbě… třeba to je chujovina, ale nedokážu na to přijít.. Pro ajax používám jquery.nette.js a jquery.ajaxform.js. Formuláře jsem zde skusil ořezat na to nejnutnější.

{form kosikRychleVlozeniForm, class => ajax}
    <!-- Jednoduché vykreslení chyb -->
    <div class="errors" n:if="$form->hasErrors()">
        {foreach $form->errors as $error}
            {!$error}{sep}<br />{/sep}
        {/foreach}
    </div>
    <span id="frmkosikRychleVlozeniForm-katalog_message"></span>
    <span id="frmkosikRychleVlozeniForm-ks_message"></span>
    <fieldset>
    <legend>Rychlé vložení do košíku</legend>
    {label katalog/} {input katalog}
    {label ks/} {input ks}
    {input vlozit_do_kosiku}
    </fieldset>
{/form}

Druhý formulář:

{snippet kosikAjax}
{if count($kosik) != 0}
{form kosikEditForm, class => ajax}
    <!-- Jednoduché vykreslení chyb -->
    <div class="errors" n:if="$form->hasErrors()">
        {foreach $form->errors as $error}
            {!$error}{sep}<br />{/sep}
        {/foreach}
    </div>
{foreach $kosik as $value}
{first}
    {var $frm_i = 0}
    <table class="basket-table">
{/first}
    {var $ksFrm = $frm_i."-ks"}
    {var $katalogFrm = $frm_i."-goods_katalog"}
    {var $poznamkaFrm = $frm_i."-poznamka"}
    <tr>
        <td>{$value['goods_nazev']|truncate:50} {label $poznamkaFrm/} {input $poznamkaFrm}</td>
        <td>{input $ksFrm} ks{input $katalogFrm}</td>
    </tr>
    {var $frm_i++}
{last}
    </table>
{/last}
{/foreach}
{/form}
{/if}
{/snippet}

zajaxuji formuláře:

<script>
 jQuery.ajaxSetup({
     cache: false,
     dataType: 'json',
     success: function (payload) {
         if (payload.snippets) {
             for (var i in payload.snippets) {
                 $('#' + i).html(payload.snippets[i]);
             }
         }
     }
 });

 // odesílání odkazů
 $('a.ajax').live('click', function (event) {
     event.preventDefault();
     $.get(this.href);
 });

 // odesílání formulářů
 $('form.ajax').live('submit', function (event) {
     event.preventDefault();
     $.post(this.action, $(this).serialize());
 });
 </script>

Toto se provede v pořádku (rychlé vložení ajaxově)

public function kosikRychleVlozeniFormSubmitted(Form $form)
 {
     try {
         $values = $form->getValues();
         $this->context->shoppingCart->add($values['katalog'], $values['ks'],'', $this->presenter, true, true);

         if($this->isAjax()) {
             $this->invalidateControl('basketSoucet');
             $this->invalidateControl('flash');
             $this->invalidateControl('basketInfo');
             $this->invalidateControl('kosikAjax');
         } else {
             $this->redirect('this');
         }
     } catch (IOException $e) {
         $form->addError($e->getMessage());
     }
 }

Toto neproběhne, když vypnu ajax, tak je to ok (ale neajaxově…)

public function editBasketFormSubmitted(Form $form)
{
    try {
        $values = $form->getValues();
        foreach($values as $val) {
            $this->context->shoppingCart->edit($val['goods_katalog'], $val['ks'], $val['poznamka'], $this->presenter, false);
        }
        $this->flashMessage('Nákupní košík přepočítán.', 'success');
        if($this->isAjax()) {
            $this->invalidateControl('basketSoucet');
            $this->invalidateControl('flash');
            $this->invalidateControl('basketInfo');
            $this->invalidateControl('kosikAjax');
        } else {
            $this->redirect('this');
        }
    } catch (IOException $e) {
        $form->addError($e->getMessage());
        $this->redirect('this');
    }
}

data plním v metodě:

public function renderBasket()
{

    $kosik = $this->context->shoppingCart;
    $this->template->kosik = $kosik->printCart();
    // helpery:
    $this->template->registerHelper('prevodDatumu', function($value, $format='d.m.Y H:i:s') {
        return date($format, strtotime($value));
    });
    $this->template->registerHelper('existObrBasket', function($value, $nahrada) {
        $isExisting = @fopen($value, 'r');
        return $isExisting ? $value : $nahrada;
    });
    $this->template->registerHelper('existObrBasketOur', function($value, $nahrada) {
        $isExisting = @fopen($_SERVER['DOCUMENT_ROOT'].'/'.$value,"r");
        return $isExisting ? $value : $nahrada;
    });
    // náhledy
    $katalog = Array();
    foreach($this->template->kosik as $value) {
        // zde to není objekt, nemůžu přistupovat jako $value->goods_katalog
        $katalog[] = $value['goods_katalog'];
    }
    $nahled = $this->modelShop->getFotogalery()->select('*')->where('goods_katalog', $katalog)->where('typ', 0)->fetchPairs("goods_katalog");
    $this->template->nahled = $nahled;
    // ceny
    $ceny= $this->modelShop->getGoods()->select('cenaSdani, katalog')->where('katalog', $katalog)->fetchPairs("katalog");
    $this->template->ceny = $ceny;
}

Editoval tatyalien (29. 5. 2012 8:47)

tatyalien
Člen | 239
+
0
-

Tak jsem ještě zjistil, že to vrací /test/basket?do=kosikEditForm-submit 500 Internal Server Error

v logu mám pak Nette\Application\BadRequestException #404 Invalid parameter name ‚0‘

Přitom argument odesílaný je pole textinputu 0 ⇒ Array(katalog, ks, poznamka), 1 ⇒ Array(katalog,ks, poznamka)… proto se nejspíš cpe name ‚0‘ jako první prvek toho pole… ale jak na tohle nastavit routu? Routy mám normálně presenter/action… když to není ajaxové odesílání, vše fachá jak má.

log:
Nette\Application\BadRequestException: ‚Invalid parameter name '0‘ in C:\xampp\htdocs\www\…\aplikace\libs\Nette\Application\UI\Presenter.php:707 @ http://localhost/…/test/basket?… @@ exception-2012–05–29–13–45–07–93bbdef2cc2bc86cb2eb0abf17689f55.html

$request:

	Nette\Application\Request(7) ▼ {
   method private => "POST" (4)
   flags private => array(1) ▼ {
      secured => FALSE
   }
   name private => "Test" (4)
   params private => array(2) ▼ {
      action => "basket" (6)
      do => "kosikEditForm-submit" (20)
   }
   post private => array(3) ▼ [
      0 => array(3) ▼ {
         poznamka => ""
         ks => "2"
         goods_katalog => "ast-A9012" (9)
      }
      1 => array(3) ▼ {
         poznamka => ""
         ks => "2"
         goods_katalog => "ast-EFLH1250M1" (14)
      }
      2 => array(3) ▼ {
         poznamka => ""
         ks => "1"
         goods_katalog => "ast-EFLH1250M2" (14)
      }
   ]
   files private => array(0)
   frozen private => TRUE
}

Editoval tatyalien (29. 5. 2012 13:48)

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Nedělá to ten parametr cache?

tatyalien
Člen | 239
+
0
-

Nevím jak to zjistit/vypnout…

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

A jo, ty tam máš false, omlouvám se.

tatyalien
Člen | 239
+
0
-

Ještě jsem zkusil změnit typ odesílání z postu na get a skočí laděnka co skáče k ajaxu… protože to vygeneruje:

test/basket?0%5Bpoznamka%5D=&0%5Bks%5D=2&0%5Bgoods_katalog%5D=ast-A9012&1%5Bpoznamka%5D=&1%5Bks%5D=2&1%5Bgoods_katalog%5D=ast-EFLH1250M1&2%5Bpoznamka%5D=&2%5Bks%5D=1&2%5Bgoods_katalog%5D=ast-EFLH1250M2&ok=P%C5%99epo%C4%8D%C3%ADtat

Ale jak na tohle nastavit routu fakt netuším, nebo jak to přenastavit… přesunout do actionu, handlu…

bojovyletoun
Člen | 667
+
0
-

nějak se mi tam nelíbí to šachování s id. Nejde to přepsat na kontejnery?

tatyalien
Člen | 239
+
0
-

No, asi mě nic jiného nezbyde… ale stejně nevím jak bych měl nastavit routu na „GET“ metodu, nebo jestli se to tím vyřeší… no jak přepíšu na kontejner metodu tak dám vědět jestli to pomohlo…

PS-asi to pomohlo, ale jsem už utahanej, zejtra to ozkouším víc a dám vědět.

Editoval tatyalien (30. 5. 2012 0:07)

tatyalien
Člen | 239
+
0
-

Tak to pomohlo… stačilo opravit továrničku na:

	...
$pole = Array();
	// tady dodáno container polozka
$sub1 = $form->addContainer('polozka');
foreach($kosik as $key => $value) {
		// toto jsem už v containeru měl
    $sub1->addContainer($i);
    $sub1[$i]->addHidden('goods_katalog', ' ');
    $sub1[$i]->addText('ks', 'ks:', 3,20)
        ->addRule($form::INTEGER, '%label musí být celé číslo.')
        ->addRule($form::RANGE, '%label musí být kladné celé číslo.', Array(0, NULL))
        ->addRule($form::MAX_LENGTH, '%label musí obsahovat maximálně %d znaků.', 20);
    $sub1[$i]->addText('poznamka', 'Poznámka:', 44,1024)
        ->addRule($form::MAX_LENGTH, '%label musí obsahovat maximálně %d znaků.', 1024);
    $i++;
    $pole[$i-1] = Array('goods_katalog' => $key, 'ks' => $value['ks'], 'poznamka' => $value['poznamka']);
}
$arr = Array('polozka' => $pole);

Jen jsem zapouzdřil jeden container do druhého a rozjelo se to. Jen se po znovunačtení formuláře nenastaví automatické opravování, ale to se myslím tady někde řešilo, tak začnu hledat…

tatyalien
Člen | 239
+
0
-

Tak jsem hledal na fóru a nic moc jsem se nedočetl… jak rozchodit java validaci na formulář, který se znovunačetl pomocí ajaxu?

Problém: načtu stránku, java validace funguje, ajaxově odešlu formulář, znovu se načte… ale už v něm nefunguje java validace…

22
Člen | 1478
+
0
-

Musíš po AJAX požadavku znovu navěstit na ten formulař tu validaci. Tuším zavolat initForm()

bojovyletoun
Člen | 667
+
0
-

A ještě dát pozor, aby se eventy nepřidaly víckrát.

tatyalien
Člen | 239
+
0
-

Tak pomohlo toto:
na konci v základním layoutu jsem dal níže uvedejen kód, kde po zpracování ajaxového požadavku invaliduji tutu část…

{snippet javaAjax}
<script>
    // napojení po načtení ajaxu live validace
	for (var i = 0; i < document.forms.length; i++) {
		Nette.initForm(document.forms[i]);
	}
</script>
{/snippet}