netteForms.js a validace nefunguje po překreslení snippetu

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

Takže zase formulářový „mág“. Mám formulář s jedním ajaxovým selectboxem (podkategorie načítané v závislosti na selectboxu kategorie) + další textová políčka a obalený ve snippetu:

{snippet form}
    {control adForm}
{/snippet}

<script type="text/javascript">
    $("#frmadForm-category").live('change', function() {
        $.get({link selectLoad!}, {"category": $(this).val()});
	return false;
    });
</script>

K validaci v prohlížeči používám netteForms.js. Po prvotním načtení se vše validuje, jak má. Pokud ale překreslím formulář pomocí ajaxu, validace přestane fungovat. Netuší někdo, v čem je problém?

Nette 2.1dev + jQuery + PHP 5.3.

Podobná témata jsem našel tady, tady a tady, ale bez řešení.

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

V success callbacku AJAXového volání je třeba zavolat Nette.load();. Překreslení formuláře totiž vytvoří pro formulář nový kus DOMu, a na něm není validace nabindovaná. netteForms.js nedělají nic jako live() v jQuery.

MartyIX
Člen | 217
+
0
-

https://github.com/…etteForms.js#L306 – nastaveni handleru se ti vola pouze v ramci udalosti window.load. Proto ti validace nemuze fungovat na prvcich, ktere dynamicky pridavas.

Editoval MartyIX (2. 4. 2012 20:08)

Vojtěch Dobeš
Gold Partner | 1316
+
0
-
{snippet form}
    {control adForm}
{/snippet}

<script type="text/javascript">
	var selectChangeCallback = function () {
		$("select[name=category]").change(function() {
			$.get({link selectLoad!}, {
				"category": $(this).val()
			}, function (payload) {
				$.nette.success(payload);
				Nette.load();
				selectChangeCallback();
			});
			return false;
		});
	};
	$(function () {
		selectChangeCallback();
	});
</script>
  1. vyhnout se použití live() je výkonnější (http://paulirish.com/…jquery-live/)
  2. nezáviset na IDčku generovaném v Nette je odolnější proti BC breakům v budoucnu (na druhou stranu použití ID je výkonnější, to jest pravda :) )

Editoval vojtech.dobes (2. 4. 2012 16:29)

net-vor
Člen | 35
+
0
-

vojtech.dobes napsal(a):

<script type="text/javascript">
	var selectChangeCallback = function () {
		$("select[name=category]").change(function() {
			$.get({link selectLoad!}, {
				"category": $(this).val()
			}, function (payload) {
				$.nette.success(payload);
				Nette.load();
				selectChangeCallback();
			});
			return false;
		});
	};
	$(function () {
		selectChangeCallback();
	});
</script>

Díky, Vojto, ale nefachčí a Firebug hlásí „Nette.load is not a function“.

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

Eh, omlouvám se, vykopíroval jsem to z jednoho projektu, kde jsem to měl upravené :) Aktuální netteForms.js takovouhle inicializační funkci nemá, takže jsem si tam dopsal:

Nette.load = function () {
	for (var i = 0; i < document.forms.length; i++) {
		Nette.initForm(document.forms[i]);
	}
};

Uvidíme, co nám David připraví v branchi jquery.

Siam
Člen | 54
+
0
-

Mám ten samý problém. Změnilo se dneska to zprovoznění netteForms a ajaxu? Zkoušel jsem jak netteForms z poslední dev verze, tak ze stable 2.0.6 a obojí mi nejde po překleslení snippetu. Ten kód co sem dal Vojta mi nefunguje.

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

Použij na Ajax nette.ajax.js, ten s netteForms.js už automaticky spolupracuje.

Siam
Člen | 54
+
0
-

vojtech.dobes:
tam mi to bohužel nejde taky. Napadá tě nějaký způsob jak zjistit příčinu? Stahoval jsem to včera (verze předtím mi nešla vůbec, tahle funguje až na to netteForms.)

Editoval Siam (17. 11. 2012 10:20)

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

Obligátně: blbě se odpovídá, když není vidět ani řádku tvého kódu.

Siam
Člen | 54
+
0
-

Zkusil jsem to dát zjednodušeně do sandboxu a výsledek byl stejný, zvlášť ty scripty šly a dohromady jenom ten ajaxový. Kód byl tento:

<?php

use Nette\Application\UI\Form;

class HomepagePresenter extends BasePresenter
{

	public function handleShowFoo()
	{
		$this->template->foo = TRUE;
		$this->invalidateControl();
	}

	public function createComponentFoo()
	{
		$form = new Form;
		$form->getElementPrototype()->class('ajax');
		$form->addText('name', 'name:')
				->setRequired('Pole se jménem musí být vyplněné.');
        $form->addSubmit('send', 'Uložit');
		$form->onSuccess[] = callback($this, 'process');
		return $form;
	}

}
{block content}
<a n:href="showFoo!" class="ajax">Show foo</a>
{snippet}
	{ifset $foo}
		{control foo}
	{/ifset}
{/snippet}
<html>
<head>
	<meta charset="UTF-8">
	<title>title</title>
	<link rel="stylesheet" media="screen,projection,tv" href="{$basePath}/css/screen.css">
	<script src="http://code.jquery.com/jquery-1.8.1.min.js"></script>
	<script src="{$basePath}/js/netteForms.js"></script>
	<script src="{$basePath}/js/nette.ajax.js"></script>
	<script>
		// inicializace nette.ajax.js
		$(function () {
		    $.nette.init();
		});
		</script>
</head>

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

Editoval Siam (17. 11. 2012 13:04)

Siam
Člen | 54
+
0
-

A html zdroják ztoho leze tento.

<div id="snippet--">
 <form id="frm-foo" class="ajax" method="post" action="/?do=foo-submit">
  <table>
   <tbody>
    <tr class="required">
     <th>
      <label class="required" for="frmfoo-name">name:
      </label>
     </th><td>
      <input id="frmfoo-name" class="text" type="text" value="" data-nette-rules="{op:':filled',msg:'Pole se jménem musí být vyplněné.'}" required="required" name="name"></td>
    </tr>
    <tr>
     <th>
     </th><td>
      <input id="frmfoo-send" class="button" type="submit" value="Uložit" name="send"></td>
    </tr>
   </tbody>
  </table>
  <div>
  </div>
 </form>
</div>
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Hm… díky za zaslání. Debugoval bych to prozkoumáním, co se odehrává na těchto řádcích, co je tam v proměnných a tak (console.log()). Jestli se tam ten cyklus projede a jestli se volá Nette.initForm. Jinak mě nenapadá, proč by to nemělo fungovat…

Siam
Člen | 54
+
0
-

Nemůžeš být prosím trochu konkrétnější? Netuším které proměnné testovat.

Zkusil jsem dát do té funkce řádky console.log(payload.snippets); console.log(window.Nette); a po kliknutí na odkaz a zobrazení toho formuláře snippet obsahoval ten formulář a window.Nette objekt se spoustou metod. Po kliknutí na formulář snippets bylo undefined a window.Nette to samé. To ti ale asi k ničemu není, neznám bohužel ani ten script a ani moc jquery…

Můžu ti poslat celý ten sandbox.

Editoval Siam (17. 11. 2012 20:50)

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

Ok, pošli celý sandbox :).

Siam
Člen | 54
+
0
-

Díky Vojto, už jsem to poslal. :)

Siam
Člen | 54
+
0
-

Díky za opravu, už to funguje! :)

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

To mám radost :)

Siam
Člen | 54
+
0
-

Akorát přestalo fungovat překreslování snippetů. :/ Po odeslání formuláře se normálně formulář zpracuje, ale vyhodí to chybu: this is not a function this($el) a vede to do části s

<script>
 $.each(this.beforeQueue, function () {
this($el);
});
</script>
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Otestuješ ještě poslední úpravu?

Siam
Člen | 54
+
0
-

Ta vypadá, že funguje. Super, díky!

Přimluval bych se ještě za nějakou minifikovanou verzi, neplánuješ jí? :)

Editoval Siam (20. 11. 2012 1:48)

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

Plánů je až moc :). Ano, rád bych ji časem zavedl.

Siam
Člen | 54
+
0
-

vojtech.dobes:
ok, to bude super. Měl bych ještě otázku. Měl bych jí napsat spíš do vlákna toho rozšíření, ale píšu to sem, protože je už zde napsaný kód o kterým chci mluvit.

Ten kód jsem poupravil tak, že pokud se ajaxově zobrazí ten formulář, tak se tklačítko „show foo“ změní na „hide foo“ a funguje to jak má.

Problém ovšem je, když na to chci použít efekt, který jsi zmínil v tom vlákně.

<script>
		$(function () {
		    $.nette.init();
		    $.nette.ext('snippets').applySnippet = function ($el, html) {
		        $el.fadeTo("fast", 0.01, function () {
		            $el.html(html).fadeTo("fast", 1);
		        });
		    };
		});
</script>

Pokud kliknu na show foo, tak se efekt i ajax použije tak jak má. Pokud ovšem potom kliknu na hide foo, tak se místo ajaxového požadavku provede normální a stránka se přesměruje. Ajaxifikace přestane funguvat. Změnil se nějak potřebný zápis, nebo je problém jinde?

Editoval Siam (20. 11. 2012 4:20)