Nefunguje invalidace u ajaxoveho formulare

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

Ahoj,

prosim vas, asi mam nekde chybu a uz nevim kde ji mam hledat. Mam jednoduchy formular, ktery bych chtel odesilat ajaxove. Tedy:

Presenter:

public function renderAdd()
	{
	}

	protected function createComponentAddForm()
	{
		$form = new \Nette\Application\UI\Form;
		$form->getElementPrototype()->class('ajax');
		$form->addText('name', 'Jméno:')->setRequired('Zadejte prosím jméno');;
		$form->addSubmit('submit', 'Odeslat');
		$form->onSuccess[] = callback($this, 'addFormSubmitted');
		return $form;
	}
	public function addFormSubmitted($form)
	{
		$values = $form->getValues();
		if($this->isAjax()){
			$this->presenter->invalidateControl('form');
		}else{
			$this->redirect('this');
		}
	}

sablona add.latte:

{block content}
	{snippet form}
		{control addForm}
	{/snippet}
{/block}

a javascript jsem pouzil z doplnku zde na webu pro jQuery. Formualr se opravdu odesle ajaxove a je vraceno:

"<form action="/e/www/admin/pages/add?do=addForm-submit" method="post" id="frm-addForm" class="ajax">

<table>
<tr class="required">
	<th><label class="required" for="frmaddForm-name">Jméno:</label></th>

	<td><input type="text" class="text" name="name" id="frmaddForm-name" required="required" data-nette-rules="{op:':filled',msg:&quot;Zadejte pros\u00edm jm\u00e9no&quot;}" value="asd" /></td>
</tr>

<tr>
	<th>&nbsp;</th>

	<td><input type="submit" class="button" name="submit_" id="frmaddForm-submit" value="Odeslat" /></td>
</tr>
</table>

<div><!--[if IE]><input type=IEbug disabled style="display:none"><![endif]--></div>
</form>
"

a jak je videt, v jsonu je u inputu

value="asd"

coz by byt asi nemelo, kdyz chci docilit toho, aby se po odeslani formular vyprazdnil.

Nevidite prosim v kodu nejakou chybu prosim?

Dekuji

22
Člen | 1478
+
0
-

třeba v submit metodě:

public function addFormSubmitted(Form $form)
{
        $values = $form->values;
        if($this->isAjax()){
			$form->setDefaults(array(),TRUE);
                $this->presenter->invalidateControl('form');
        }else{
                $this->redirect('this');
        }
}
tomasnikl
Člen | 137
+
0
-

to se omlouvam, stoural sjem se v kodu tak az jsem to smazal. Samozrejme tam tento kus kodu mam a i tak mi to vraci to co jsem vyse zminoval.

22
Člen | 1478
+
0
-

musíš ještě zavolat po submitu $.nette.success(payload), ale už to tu bylo tak párkrát řešeno..

$('input.ok').live('click', function(){
	$(this).closest('form').ajaxSubmit(function(payload){
		$.nette.success(payload);
	});
	return false;
});
tomasnikl
Člen | 137
+
0
-

uz to resim cely den a uz jsem myslel ze to pomuze ale ne… i pres tu tvou radu mi po odeslani stale v inputu zustavaji hodnoty ktere jsem vyplnil pred odeslanim. Nemate nekdo zivou ukazku abych omrknul ty javascripty? i kdyz se mi zda ze v nich chybu mit nebudu..

22
Člen | 1478
+
0
-

a invaliduje se ti normální snippet bez formuláře? Jak poznáš, že ten javascript proběhl? Je v proměnné payload něco?

tomasnikl
Člen | 137
+
0
-

Tak jsem vyzkousel, vytvoril jsem si novy snippet v sablone, a ten se mi neinvalidoval, zda to pisu spravne. V tomto novem snippetu jsem z presenteru predaval promenou test s hodnotou XXX a po odeslani formulare jsem jeji hodnotu chtel zmenit na YYY.. v sablone ovsem i po odeslani formulare je text XXX, takze ani snippet bez formulare se nezmenil. Takze chyba bude asi zde, ze se neinvaliduje snippet.

Jinak promena payload je naplnena. Je v ni snippet s formularem

jeste jednou ukazu aktualni kod:
Presenter:

	public function renderAdd()
	{
		$this->template->test = 'test1';
	}

	protected function createComponentAddForm()
	{
		$form = new \Nette\Application\UI\Form;
		$form->getElementPrototype()->class('ajax');
		$form->addText('name', 'Titulek stránky:')
				->setRequired('Zadejte prosím titulek stránky')
				->getControlPrototype()->class('slug-title');
		$form->addText('menu_name', 'Titulek v menu:');
		$form->addText('slug', 'URL slug:')
				->setRequired('Zadejte prosím URL slug')
				->getControlPrototype()->class('slug');;
		$form->addSelect('status', 'Viditelnost:', array(1=>'Viditelná', 0=>'Skrytá'));
		$form->addText('head_title', 'Titulek v hlavičce:');
		$form->addTextArea('head_description', 'Popis stránky v hlavičce:');
		$form->addText('head_keywords', 'Klíčová slova:');
		$form->addTextArea('body', 'Obsah stránky:')->setRequired('Zadejte prosím Obsah stránky');
		$form->addSubmit('submit', 'Odeslat');
		$form->onSuccess[] = callback($this, 'addFormSubmitted');

		return $form;
	}
	public function addFormSubmitted($form)
	{
		$values = $form->getValues();
		$form->setDefaults(array(), TRUE);
		if($this->isAjax()){
			$this->template->test = 'test2';
			$this->invalidateControl('formular');
			$this->invalidateControl('test');
		}else{
			$this->redirect('this');
		}
	}

sablona:

{block content}
	{snippet test}
		{$test}
	{/snippet}
	{snippet formular}
		{control addForm}
	{/snippet}
{/block}
22
Člen | 1478
+
0
-

řek bych, že nemáš zalinkovanej jquery.nette.js

tomasnikl
Člen | 137
+
0
-

pokdu je jquery.nette.js toto:

/**
 * AJAX Nette Framwork plugin for jQuery
 *
 * @copyright   Copyright (c) 2009 Jan Marek
 * @license     MIT
 * @link        http://nettephp.com/cs/extras/jquery-ajax
 * @version     0.2
 */

jQuery.extend({
	nette: {
		updateSnippet: function (id, html) {
			$("#" + id).html(html);
		},

		success: function (payload) {
			// redirect
			if (payload.redirect) {
				window.location.href = payload.redirect;
				return;
			}

			// snippets
			if (payload.snippets) {
				for (var i in payload.snippets) {
					jQuery.nette.updateSnippet(i, payload.snippets[i]);
				}
			}
		}
	}
});

jQuery.ajaxSetup({
	success: jQuery.nette.success,
	dataType: "json"
});

tak ano.. zalinkovani VSECH JS jsem uz zkousel.. dokonce jsem zkousel odebrat vsechny JS ktere nesouvisi s ajaxem a s nette a take to nepomohlo..

jeste me napada, jeslti nemuze byt problem v zanorenych snippetech (ale ty uz jsem take zkousel odebrat).

mam v sablone @layout.latte neco takoveho:

<div class="content left">
				{snippet content}
					{include #content}
				{/snippet}
			</div>

a sablona zminena v predchozim prispevku se includuje jako content.. takze vpodstate je tam neco takoveho:

{snippet content}
	{snippet formular}
		komponenta pro vykresleni formulare
	{/snippet}
{/snippet}

jelikoz cela aplikace je zamyslena ajaxove, to znamena ze pri kliknuti na polozku v menu se ajaxem prekresli snippet content na pozadovanou stranku a toto obstarava metoda beforeRender v presenteru:

	public function beforeRender()
	{
		parent::beforeRender();
		if($this->isAjax())
		{
			$this->invalidateControl('content');
		}
	}
	// a zde nasleduje zbytek presenteru, ktery je zminen v mem predchozim prispevku
tomasnikl
Člen | 137
+
0
-

ted jsem jeste overoval invalidaci snippetu na jine strance (stejny presenter). Tam mam vypis dat z databaze a strankovani. Strankovani je resene ajaxem, takze kdyz kliknu na „stranka 1“ tak se mi dany snippet prekresli, takze jak tak koukam, tak mi to funguje, jen u formulare s tim je problem

Editoval tomasnikl (23. 9. 2011 19:06)

tomasnikl
Člen | 137
+
0
-

tak jeste jedna vec:
vypnul jsem ajaxove odesilani a vypnul jsem redirect po odeslani a trochu upravil kod. Predpokladam, ze by to po odeslani formulare melo nastavit prazdne hodnoty formulare a pote je vypsat na stranku (dump).. ovsem po odeslani formulare me to jeho hodnoty nevymaze a na stranku mi to vyprskne hodnoty, ktere jsem do formulare zadal.. takze chyba bude asi zde

public function addFormSubmitted($form)
	{
		$values = $form->getValues();
		$form->setDefaults(array(), TRUE);
		dump($form->getValues());
		if($this->isAjax())
		{
			$this->template->test = 'test2';
			$this->invalidateControl('formular');
			$this->invalidateControl('test');
		}else{
			//$this->redirect('this');
		}
	}
22
Člen | 1478
+
0
-

problém je spíš se snippet vložený přes include. Teoreticky ten snippet ‚content‘ nepotřebuješ nebo to pořeš tak, aby jsi ho nepotřeboval.

Edit: pokud vypneš ajax a není tam redirect, tak je jasné, že hodnoty tam zůstanou :-)

Editoval 22 (23. 9. 2011 19:18)

tomasnikl
Člen | 137
+
0
-

no to bych asi zatim neresil.. ja jsem ten snippet content uz zkousel smazat a nenacitat stranky ajaxem..

ale ted mozna spatne chapu.. ja myslel ze takoveto reseni je spravne.. kdyz budu predpokladat, ze mam sablonou @layout.latte ve ktere mam:

<html>
<head>
</head>
<body>
{include #content}
</body>
</html>

a pote mam presenter PagesPresenter.php kde mam napr:

renderDefault(){
//...... nejaky kod
}

a samozrejme sablonu templates/Pages/default.latte a v ni:

{block content}
	{snippet nejakySnippet}
		napr formular ve snippetu ktery po ajaxu prekreslim
	{/snippet}
{/block}

Toto je spatne reseni? Ja myslel ze takto by se weby v nette mely „stavet“, nebo lepe reseno, ze takto je zamysleno pouziti blocku..

//edit:

k tomu redirectu.. tim ze redirectnu tak je mi jasne ze hodnoty formulare ztratim.. ale myslel jsem ze kdyz nastavim formulari „prazdne“ hodnoty a pote je zkusim vypsat tak by logicky mely byt „prazdne“..
chapu to jako:

<?php
// vypise hodnota = 1
$array = array('hodnota' => 1);
print_r($array);

//nevypie nic (toto chapu jako zminene vymazani hodnot formulare bez redirectu)
$array = array('hodnota' => 1);
$array = array();
print_r($array);

//nevypie nic
$array = array('hodnota' => 1);
header('location: jina-stranka-kde-budu-chtit-vypsat_print_r($array()).php');
print_r($array);
?>

Nebo se zmineny kod v predchozim prispevku s prepsanim hodnot chova jinak nez takto?

Editoval tomasnikl (23. 9. 2011 19:28)

22
Člen | 1478
+
0
-

já jsem ale mluvil o includovaném snippetu, snippet !== block, je to chyba, která už tu straší poměrně dlouho a ještě se nezadařilo opravit. Dá se to obcházet dědičnosti šablon, kde se include vyhneš.

Editoval 22 (23. 9. 2011 19:27)

tomasnikl
Člen | 137
+
0
-

ted tomu asi moc nerozumim, takze pokud pouzivam {include #nejaky_blok} a v danem bloku pouziju {snippet neco} tak to muze delat problemy (rikam muze, protoze u jine stranky, kde nepouzivam ajax na formular ale na odkazy mi vse funguje v poradku)?

tomasnikl
Člen | 137
+
0
-

aha, uz ti asi rozumim.. ja jsem to spise spatne vysvetlil, v sablone @layout.latte mam:

{snippet content}
	{include #content} <!-- includuju block content ne snippet -->
{/snippet}

a v sablone pro nejakou stranku mam:

{block content}
	{snippet formular}
		formular
	{/snippet}
{/block}

takze se neincluduje snippet ale block ve kterem je az snippet… nestastne pojmenovani bloku „content“ a snippetu „content“ asi mate

22
Člen | 1478
+
0
-

..jj, souvisí imho s tímto. Pokud ten obalový snippet odstraníš, tak to funguje předpokládám?

tomasnikl
Člen | 137
+
0
-

prave ze ne, jak jsem uz psal, ten obalovy snippet jsem odstranil a celou tu funkcnost s jeho invalidaci jsem z kodu take dal pryc (zakomentoval). A nefunguje to i tak… Ale jak jsem psal, i kdyz tam ten obalovy snippet je, tak mi to na jine strance funguje (jak jsem jiz znimoval, neni na te strance sice pouzit formular, ale ajaxove odkazy..)

22
Člen | 1478
+
0
-

a co když použiješ místo?:

{snippet content}
        {include #content} <!-- includuju block content ne snippet -->
{/snippet}

//toto
{snippet content}
        {block #content}{/block} <!-- includuju block content ne snippet -->
{/snippet}

Editoval 22 (23. 9. 2011 19:49)

tomasnikl
Člen | 137
+
0
-

bohuzel.. vse zustava pri starem, po ajaxovem odeslani formulare v nem hodnoty zustavaji

tomasnikl
Člen | 137
+
0
-

asi spravne nechapu jak to funguje… Kdyz kliknu na odeslat formular tak se odesle ajaxovy pozadevek. Dostanu se do metody addFormSubmitted a v ni nastvim formulari defaultni hodnoty rovny prazdnemu poli. Jinymi slovy formular vyprazdnim. Ale kdy nette odesle zpet json s obsahem snippetu? v metode addFormSubmitted? protoze se mi zda ze na to jdu nejak spatne.. zda se mi, ze nette odesle json s obsahem snippetu uz drive nez ja vyprazdnim formular.

22
Člen | 1478
+
0
-

to je divný.. Tohle mi normálně funguje.. moment, vyzkouším to.

Edit: Nebo mi někam pošli na uloz.to třeba tu aplikaci…

Editoval 22 (23. 9. 2011 20:08)

tomasnikl
Člen | 137
+
0
-

dej mi email, poslu na maila

22
Člen | 1478
+
0
-

condor.mig<at>gmail.com

bojovyletoun
Člen | 667
+
0
-

odešleš formulář → což presenter vyhodnotí jako signál pro komponentu formuláře → formulář si sám obslouží signály → fireEvents() → zavolají se callbacky na tlačítku (onSuccess[]) → tvoje funkce nastaví formuláři prázdné hodnoty ( + ještě je nutné nvaLidateCOntrol), nedojde ke přesměrování → vykresluje se stejné stránka → jedná se o ajaxový požadavek → šablona najde jen části, které se musí překreslit a uloží je do payloadu presenteru, ten je pak pošle v JSONU.

tomasnikl
Člen | 137
+
0
-

Tak problem byl zde:

$form->setDefaults(array(), TRUE);

misto toho je potreba pouzit:

$form->setValues(array(), TRUE);

Takze dekuji moc predevsim 22 za cas, ktery venoval reseni tohoto problemu a doufam ze to nekomu v budoucnu pomuze.

tomasnikl
Člen | 137
+
0
-

bojovyletoun:
super, dekuju moc, to je krasne napsane.. ted mi to je jasne. dekuju moc!!!!