Přepočítání košíku s odmazáním

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

Dobrý den,
rozjel jsem si přidávání a aktualizaci košíku pomocí ajaxu, funguje to spolehlivě, ale když přepočítávám košík a přitom z něj odmazávám, tak to nefunguje tak jak by mělo.
Příklad:
mám v košíku: kat-1 1ks, kat-2 2ks, kat-3 3ks… změním počet kusů na 0 u položky kat-2 a po odeslání by se měl zobrazit tedy formulář s:
kat-1 1ks, kat-3 3ks, ale vykreslí se mě kat-1 1ks, kat-2 0ks, kat-3 3ks, když udělám aktualizaci stránky (F5) je vže ok.
Někdy se i vykreslí: kat-1 1ks, kat-3 0ks..
Nevím kde je zakopanej pes, jestli něco dělám blbě u ajaxu…?

Zde jsem to kdyžtak sesumíroval do mini_sendboxu.

Továrničku na editaci mám:

// jednoduchá továrnička
    protected function createComponentBasketEditFormNew()
    {
        $form = new Form();
	// natáhnu si kolik položek mám vytvořit
        $kosik = $this->context->shoppingCart->printCartNew();
        $i = 0;
        $pole = Array();
        $polozka = $form->addContainer('polozka');
        foreach($kosik as $value) {
            if($value['ks'] != 0){
                $polozka->addContainer($i);
                $polozka[$i]->addText('goods_katalog', 'katalog');
                $polozka[$i]->addText('ks', 'ks:', 3,20);
                $polozka[$i]->addText('poznamka', 'Poznámka:', 44,1024);
                $i++;
                $pole[$i-1] = Array('goods_katalog' => $value['goods_katalog'], 'ks' => $value['ks'], 'poznamka' => $value['poznamka']);
            }
        }
        $arr = Array('polozka' => $pole);
        // caption dodané v render metodě - obrázek
        $form->addSubmit('ok', 'Odeslat');
        $form->setDefaults($arr);
        $form->onSuccess[] = callback($this, 'editBasketFormSubmitted');
        // nastavení třídy pro formulář na ajax
        $form->getElementPrototype()->class("ajax");
        return $form;
    }

    public function editBasketFormSubmitted(Form $form)
    {
        try {
            $values = $form->getValues();
            foreach($values->polozka 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('basketEdit');
                $this->invalidateControl('javaAjax');
            } else {
                $this->redirect('this');
            }
        } catch (IOException $e) {
            $form->addError($e->getMessage());
        }
    }

třída shopping cart je kdyžtak v sendobxu v linku nahoře.

LeonardoCA
Člen | 296
+
0
-

V rychlosti jsem na to mrknul, chyba je podle mne v tom, že komponenta je ve chvíli kdy se zpracovává handle již vytvořena. InvalidateControl znamená jen znovu vykreslit, ale ty položky košíku, které mají hodnotu 0 jsou již v definici formuláře a vykreslí se taky.

Jak to snadno a vtipně ošetřit zatím nevím a také by mne to zajímalo.

Editováno:
Buď zahodit komponentu a vytvořit znovu nebo ji nějak modifikovat?

Editoval LeonardoCA (4. 6. 2012 13:27)

tatyalien
Člen | 239
+
0
-

Taky jsem si říkal, že komponenta už nejspíš je někde vytvořená a nebere v potaz, že jsem jí invalidoval… u košíku mám i křížek na odstranění jednotlivé položky z košíku přes hendl a vše ok… ale chtěl jsem to i povolit, když má uživatel víc věcí v košíku a chce odmazat třeba 3 naráz… (no lépe řečeno, shop si jen dělám v nette pro své programátorské blbnutí :-D)

LeonardoCA
Člen | 296
+
0
-

zkus si pridat do kodu
Debugger::fireLog(‚createComponentBasketEditFormNew‘);
Debugger::fireLog(‚editBasketFormSubmitted‘);
do odpovidajicich trid a do handlaru toho mazani take vypis a sleduj v jakem poradi se ti funkce volaji …

tatyalien
Člen | 239
+
0
-

Tak dvě situace:

  • Situace 1:

Prvotní načtení:

  1. render start
  2. render konec
  3. (zde se nepřipojila komponenta)

ajax odeslani:

  1. továrna start
  2. // odesílal jsem kat-1 1, kat-2 0, kat-3 3
[Object { goods_katalog="kat-1", goods_nazev="katalog 1", ks=1, více...}, Object { goods_katalog="kat-2", goods_nazev="katalog 2", ks=2, více...}, Object { goods_katalog="kat-3", goods_nazev="katalog 3", ks=3, více...}]
  1. továrna konec
  2. editBasketFormSubmitted start
[Object { goods_katalog="kat-1", goods_nazev="katalog 1", ks=1, více...}, Object { goods_katalog="kat-3", goods_nazev="katalog 3", ks=3, více...}]

// v sessionu košíku je nyní vše ok

  1. editBasketFormSubmitted konec
  2. render start
  3. render konec
  4. ale nevrátí se mě nově aktualizovaný formulář, je zde furt z prvotního
  • Situace 2:

když dám do render metody:

$frm = $this['basketEditFormNew'];
$frm['ok']->caption = "ok A";

// jen abych přistoupil k formuláři…

Začátek:

  1. render start
  2. továrna start
  3. // načtení košíku kat-1 1, kat-2 2, kat-3 3
[Object { goods_katalog="kat-1", goods_nazev="katalog 1", ks=1, více...}, Object { goods_katalog="kat-2", goods_nazev="katalog 2", ks=2, více...}, Object { goods_katalog="kat-3", goods_nazev="katalog 3", ks=3, více...}]
  1. továrna konec
  2. render konec

ajax odeslání:

  1. továrna start
  2. // staré data kat-1 1, kat-2 2, kat-3 3
[Object { goods_katalog="kat-1", goods_nazev="katalog 1", ks=1, více...}, Object { goods_katalog="kat-2", goods_nazev="katalog 2", ks=2, více...}, Object { goods_katalog="kat-3", goods_nazev="katalog 3", ks=3, více...}]
  1. továrna konec
  2. editBasketFormSubmitted start

// v košíku již vše ok kat-2 jsem odmazával

[Object { goods_katalog="kat-1", goods_nazev="katalog 1", ks=1, více...}, Object { goods_katalog="kat-3", goods_nazev="katalog 3", ks=3, více...}]
  1. editBasketFormSubmitted konec
  2. render start
  3. // zde se nezavolá továrna nově…
  4. render konec

Editoval tatyalien (5. 6. 2012 11:57)

22
Člen | 1478
+
0
-

Nevím, co se tu přesně řeší, ale doporučil bych ti se podívat na životní cyklus presenteru

Data bych plnil v action metodě a handlerem se dají měnit a invalidovat snippet/y

tatyalien
Člen | 239
+
0
-

Ano, ale když vytvářím formulář z neznámého počtu prvků, tak mě to asi nepomůže ne? Při tvorbě formuláře si šáhnu do sessionu a zjistím kolik kontejnerů vytvořit…

tatyalien
Člen | 239
+
0
-

VYŘEŠENO:
Případné řešení je ze starého vlákna:

public function renderBasket()
{
	...
    if($this->isAjax()) {
        // promazání formuláře a vytvoření formuláře
        unset($this['basketEditForm']);
        //... zvýšit počet řádků v session (já to zvětšuji při odesláním formuláře)
        // a v továrničce si načtu kolik je potřeba vytvořit prvků v košíku...
        $this->template->basketEditForm = $this->createComponentBasketEditForm();
        $this->invalidateControl('title');
    }
}

Editoval tatyalien (6. 6. 2012 12:49)

Aurielle
Člen | 1281
+
0
-

Opravdu je nutné tu továrničku volat přímo?

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

Potřebuje v rámci jednoho requestu sestavit formulář, provést jeho zpracování a znovu sestavit ten samý formulář.

tatyalien
Člen | 239
+
0
-

Nejspíše ano, protože pokud jsem to nezavolal, tak komponenta měla staré data, takto se promazala a bylo to ok, vzorovej příklad bez unsetnutí je v prvním příspěvku, když se tam dodá unset tak vše funguje jak má…

Edit: Pokud se jen přepočítávaly hodnoty, není potřeba unsetnout, ale pokud se nastavilo u položek 0 ks tak tu hodnotu odmazávám a pak je potřeba formulář znovu sestavit.

Editoval tatyalien (6. 6. 2012 14:42)