Překreslení formuláře bez odeslání

d@rkWolf
Člen | 162
+
0
-

Zdravím, poradil by mi prosím někdo, kde dělám chybu?

Mám formulář, který je obalený ve snippetu a který potřebuju, aby se při jakékoliv změně překreslil, ale neodeslal-na odeslání je tam NE-ajaxový submit button.

<?php
{snippet summary}

<form id="frm-orderForm" ...>
...
</form

{/snippet}
?>

k tomu handle

<?php
public function handleRecalculateCart() {
	$data = $this->presenter->getHttpRequest()->getPost();
	...
	$this->redrawControl('summary');
}
?>

a js v samostatném souboru s js scripty

<script>
    $(document).on('change', '#frm-orderForm', function() {
        $.nette.ajax({
            type: 'POST',
            url :'?do=recalculateCart',
            data: $(this).serialize()
        });
    });
</script>

Z nějakého mě nepochopitelného důvodu se mi ten formulář při změně odesílá, jako bych kliknul na Submit, klasicky postem, kterej překresluje obsah na dokončení, místo aby se překreslil snippet.

CZechBoY
Člen | 3608
+
0
-

no vsak tam mas on(change, ...)… co bys cekal ze to bude delat?

resp. co chces aby to delalo?

d@rkWolf
Člen | 162
+
0
-

No já potřebuju, aby se mi při on(change) uložily aktuální údaje z polí do session(to mám v tom handlu) a překreslil se snippet s celým tím formem, jenže teď se stanou 2 věci, provede se ajax, jenže zároveň s ním se provede i normální ne-ajaxový post toho formu jako bych kliknul na normální submit tlačítko, takže zákazník místo aktualizované ceny nebo jiných údajů okamžitě odešle objednávku.

Tohle chování se objevilo po tom, co jsem upgradoval Nette z 2.2.7 na 2.3.10, na 2.2.7 se to s naprosto stejným kódem chovalo tak jak potřebuju. Zkusil jsem aktualizovat nette.ajax, jestli není nějaký problém v něm, ale nic se nezměnilo.

CZechBoY
Člen | 3608
+
0
-

Chyba bude v js.
Predej si event a potom na nem tavolej preventDefault(), idealne hned na zacatku callbacku.

$(document).on('change', 'tvuj selector', function(e) {
e.preventDefault();
//... tvuj kod
});

Editoval CZechBoY (18. 6. 2017 10:19)

d@rkWolf
Člen | 162
+
0
-

CZechBoY napsal(a):

Chyba bude v js.
Predej si event a potom na nem tavolej preventDefault(), idealne hned na zacatku callbacku.

$(document).on('change', 'tvuj selector', function(e) {
e.preventDefault();
//... tvuj kod
});

Mám tam na konci return false, tím to není, zkoušel jsem i preventDefault(), to sice zablokovalo odeslání, ale přesto provedlo zpracování odeslaného formuláře(public function orderFormSubmitted), takže pak nastala úplně problematická situace, protože při dalším refreshi všecko z koše zmizelo, jelikož neviditelná orderFormSubmitted vše odeslala a zrušila všecky data ze session)

d@rkWolf
Člen | 162
+
+1
-

Ale asi sem na to přišel:

totiž nové Nette přidává k FormData do: orderForm-submit, asi tak nějak automaticky, takže když jsem v JS použil $(this).serialize(), dostal jsem to do těch odeslaných dat, v podstatě tam byly 2× do:, jedno recalculateCart jako parametr adresy a druhý orderForm-submit v datech formuláře, no a to orderForm-submit si následně odchytila funkce co zpracovává odeslání formuláře

takže jsem to upravil takto, prostě z tama to orderForm-submit vyhodím:

<script>
$(document).on('change', '#frm-orderForm', function(e) {
    var data = $(this).serialize();
    data = data.replace('&do=orderForm-submit', '');

    $.nette.ajax({
        type: 'POST',
        url :'?do=recalculateCart',
        data: data
    });
    return false;
});
</script>
Jan Mikeš
Člen | 771
+
+3
-

Ahoj, tvůj způsob se mi moc nelíbí, zdá se mi dost nečisté ručně serializovat data a handlovat sám request na form s do parametrem, to je opravdu fujky. Poradím ti, jak to děláme my.

Přidám si nový button, který slouží na ukládání dat, v šabloně ho přes css schovám:

$form->addSubmit('saveData', 'save')
	->setValidationScope(FALSE)
	->onClick[] = function(Button $button) use ($saveButtonCallback) {
		$values = $button->getForm()->getValues(TRUE);
		$saveButtonCallback($values);
	};

Jen pro doplnění, $saveButtonCallback je callable předáno při vytváření instance formuláře

public function create($locale, array $inputs, callable $successCallback, callable $saveButtonCallback)

setValidationScope(false) ti navíc vypne validační pravidla, takže ukládá vždy aktuální data bez ohledu na validaci.

U nás to ukládáme na pozadí takto:

window.setInterval(function() {
   $("[data-periodic-save]").click();
}, 60000);

Nic ale nebrání to navázat na tvůj handler onChange

Zbývá tlačítko vykreslit v šabloně, schovat ho, ajax nastavení atd. dle libosti:

{input saveData, data-periodic-save=>"", style=>"display: none;", data-ajax-body-class=>"no-spinner", data-ajax-off=>"[unique, abort, history, initOnAjax, modals, confirm, ajaxCloseClick, initFormsValidation, ajaxForms]"}

Pro úplnost, formulář pak vytvářím např takto:

	protected function createComponentForm()
	{
		$saveCallback = function(array $values) {
			$this->storage->store($values);
			$this->onValuesSaved();
		};

		$successCallback = function() {
			$this->storage->clean();
			$this->onFormSuccess();
		};

		return $this->formFactory->create($this->locale, $this->inputs, $successCallback, $saveCallback);
	}

Editoval Jan Mikeš (18. 6. 2017 15:10)

d@rkWolf
Člen | 162
+
0
-

Jo to vypadá hezky, vono v tom košíku by toho bylo potřeba předělat mnohem víc. Jenže od té doby, co sem to „podědil“ mám většinou sotva tak čas opravovat chyby, todle bylo nutný nějak rychle opravit doslova do 5 minut než otevřou a začnou jim tam posílat lidi objednávky místo výběru platební metody… Vrchol byl upgrade Nette a dalších komponent na verze kompatibilní s php7 a následné upravení co bylo třeba, což aspoň na chvíli zmírní stížnosti klientů na pomalost systému.

Každopádně si to připíšu k „To Do“

chemix
Nette Core | 1294
+
0
-

@JanMikeš neudelal by jsi z toho fungujici miniukazku na planette?