Dodatocna vlastna javascript funkcia v onsubmit

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

Zdravim,

chcem pridat vlastnu JS funkciu, ktora sa vykona pri odoslani formulara, do AppForm, s tym, ze sa zachova validacia formulara.

Inak povedane, ako mozem nastavit volanie urcitej JS funkcie po uspesnej validacii formulara a este pred odoslanim? Cim dlhsie nad tym premyslam, tym menej napadov na moznu realizaciu mam.

Vdaka za pomoc a napady

MIKI
Člen | 34
+
0
-

Dnes som sa tomu zase trochu venoval a nasiel som zrejme funkcne riesenie.

AppForm()->addSubmit()->getControlPrototype()->onclick('js_funkcia()');

V pripade jednoducheho formulara to je funkcne.

Taktiez som si aj nasiel chybu v JS funkcii, kvoli ktorej mi ani tato konstrukcia najprv nefungovala.

westrem
Člen | 398
+
0
-

A si si na 100% isty, ze tvoja JS funkcia sa vykonava az po uspesnej JS validacii?

MIKI
Člen | 34
+
0
-

westrem napsal(a):

Diky, vedel som, ze to nebude take jednoduche :)
Bohuzial, nevykonava sa. Najprv sa spravi moja JS funkcia a potom je validacia. A to je zle.
Je mozne to sice v JS funkcii osetrit, ale neexistuje lepsi sposob ako to spravit aby to bolo po validacii? (bez zasahu do mojej JS funkcie?)

jtousek
Člen | 951
+
0
-

Jako nejlepší řešení mi připadá nějak upravit netteForms.js, aby volalo nějaký callback ještě než formulář odešle. Doporučuji to dát tady na fórum jako feature request.

westrem
Člen | 398
+
0
-

Aku verziu Nette pouzivas? Ak 0.9.* tak existuje riesenie (trosku zdlhave) ale hodne ciste bez explicitneho zasahu do frameworku.

O pridavanie JS validacie sa stara InstantClientScript, ktory na tomto riadku pridava JS validaciu. Ty tam chces mat svoju JS spolu s validaciou cize tam chces toto:

return nette.validateForm(this) && tvoja_JS_funkcia()

K tomu aby si to dosiahol, si proste vytvor vlastny objekt, ktory bude totozny ako InstantClientScript len zmenis ten spominany riadok (podedit nemozes, pretoze je final – tzn bud smaz final a poded a prepis si tu funkciu alebo vytvor ten identicky objekt).

Dalej, aby sa pri renderingu uplatnil tvoj InstantClientScript je potrebne povedat to Rendereru, tzn poded ConventionalRenderer a zmen tento riadok tak aby vracal instanciu tvojho ClientScriptu (tzn. v praxi podedis od Conventional rendereru a prepises (override) tu funkciu getClientScript).

Tymto sposobom by si mal dosiahnut to, ze najskor sa spravi validacia (v JS podmienke je 1.) a nasledne sa vykona este tvoja JS_funkcia.

Este len tak z kuriozity: co chces tou JS funkciou spravit? Ci to nejde nahodou obecne aj inak ako takto :) a aby sme tu neriesili zbytocne nieco komplikovane.

redhead
Člen | 1313
+
0
-

westrem napsal

Vytvořit musí novou třídu (ne objekt) totožný s InstantClientScriptem (+ změnu té metody). A nemusí poděďovat ConventionalRenderer, stačí:

$form->getRenderer()->setClientScript(new TaNovaTrida);

Editoval redhead (15. 9. 2010 17:16)

westrem
Člen | 398
+
0
-

redhead napsal

Pardon pardon, bol som tak zazrany do napisania riesenia, ze som trochu plietol triedy a objekty .. mas samozrejme pravdu.

Taktiez s tym nastavovanim ClienScriptu som pozabudol, ze je tam aj setter (ked ma clovek otvorenych 5+ API okien, trochu strati prehlad co kde uz je)

MIKI
Člen | 34
+
0
-

redhead napsal(a):

westrem napsal

Diky obom. Presne toto som potreboval :)

Vysledok je asi takyto: Vytvoril som si novu triedu (skopirovany subor) MyInstantClientScript, do ktoreho som pridal nasledujuci text:

  /** @var array */
  private $afterValidateJS;

  /** @var array */
  private $beforeValidateJS;

...

	public function __construct(Form $form)
	{
		$this->form = $form;
+		$this->afterValidateJS = array();
+		$this->beforeValidateJS = array();
	}

...

  /**
  * Add JavaScript function after Form Validation on Submit
  */
  public function addAfterValidateJS($jsfun)
  {
    $this->afterValidateJS[] = $jsfun;
  }
  /**
  * Add JavaScript function before Form Validation on Submit
  */
  public function addBeforeValidateJS($jsfun)
  {
    $this->beforeValidateJS[] = $jsfun;
  }
  /**
  * Generate result onsubmit with JavaScript function
  */
  private function getFormOnSubmitValidate()
  {
    $validate = 'nette.validateForm(this)';
    $array = array_merge($this->beforeValidateJS, array($validate), $this->afterValidateJS);
    return 'return '.join(' && ', $array);
  }

A upravil vo funkcii enable() riadok L1 na riadok L2

		if ($this->validateScripts || $this->toggleScript) {
			if ($this->central) {
-				$this->form->getElementPrototype()->onsubmit("return nette.validateForm(this)", TRUE); // L1
+				$this->form->getElementPrototype()->onsubmit($this->getFormOnSubmitValidate(), TRUE); // L2

			} else {

Pri vytvarani formulara

$MyInstantCS = new MyInstantClientScript($form);
$MyInstantCS->addAfterValidateJS('mojaFunkcia()');
$form->getRenderer()->setClientScript($MyInstantCS);

A vo vyslednom formulari sa teda vygeneruje:

<form action="__ACTION__" method="post" id="__ID__" onsubmit="return nette.validateForm(this) &amp;&amp; mojaFunkcia()">

Sice sa mi tam nepacia tie & ale v Opere a FireFoxe to funguje ako ma :)

Este raz diky za napad! A dufam, ze sa toto niekomu zide taktiez :)