Spojení formulářů s AJAXem

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Grudl
Nette Core | 8218
+
0
-

Občas tu padnou dotazy, jak spojit formuláře s AJAXem, nebo jak vybrání položky v select boxu načíst jiný box atd. Řešení existuje samozřejmě více, chtěl bych je i probrat na školení PHP, Toto je jedno z nich (neříkám že vzorové):

	public function actionDefault()
	{
		$this->template->form = $form = new AppForm($this, 'form');

		$form->addSelect('lokalita', 'Vyberte si lokalitu:', $lokality)
			->addRule(Form::FILLED, 'Vyberte lokalitu');

		$form->addSelect('termin', 'Zvolte si termín:') // zatim bez hodnot
			->addRule(Form::FILLED, 'Vyberte termín');

		$form->addSelect('den', 'A vyberte si den:') // zatim bez hodnot
			->addRule(Form::FILLED, 'Vyberte den');

		$form->addSubmit('submit1', 'Odeslat');

		// nastavime události onchange:
		$form['lokalita']->getControlPrototype()
			->onchange('loadBox(1, this.value);');
		$form['termin']->getControlPrototype()
			->onchange('loadBox(2, this.value);');
		$form['den']->getControlPrototype()
			->onchange('loadBox(3, this.value);');

		if ($form->isSubmitted()) {
			// teprve nyni dosadime hodnoty
			$form['termin']->setItems(...);
			$form['den']->setItems(...);

			if ($form->isValid()) {
				...
			}

		} else {
			$form['termin']->setDisabled();
			$form['den']->setDisabled();
			$form['submit1']->setDisabled();
		}
	}

Jako obsluhu události onchange jsem prvkům select nastavil volání funkce loadBox(). Ta může vypadat třeba takto (využívá se jQuery):

function loadBox(phase, value)
{
	if (phase === 1) {
		// zvolena hodnota prvniho select boxu
		$('#frmform-den').attr('disabled', true);
		$('#frmform-den').val(0);
		$('#frmform-submit1').attr('disabled', true);

		// zobrazi symbol, že se něco načítá
		spinner();

		// natáhne obsah druhého selectboxu pomocí AJAXu
		$.get("?do=loadData", {"value": value, "phase": phase}, function(data) {
			$('#frmform-termin').parent().html(data);
  		});

	} else if (phase === 2) {
		// zvolena hodnota druheho select boxu
		$('#frmform-submit1').attr('disabled', true);

		// zobrazi symbol, že se něco načítá
		spinner();

		// natáhne obsah třetího selectboxu pomocí AJAXu
		$.get("?do=loadData", {"value": value, "phase": phase}, function(data) {
			$('#frmform-den').parent().html(data);
  		});

	} else if (phase === 3) {
		// zvolena hodnota tretiho select boxu, povolí tlačítko submit
		$('#frmform-submit1').attr('disabled', true);
	}
}

Funkce zase vyvolá signál loadData, jehož handler může vypadat takto:

	public function handleLoadData($phase, $value)
	{
		$form = $this->template->form;

		if ($phase == 1) {
			// naplníme select box prvky a vypíšeme na výstup
			$form['termin']->setItems(...);
			echo $form['termin']->getControl();

		} elseif ($phase == 2) {
			$form['den']->setItems(...);
			echo $form['den']->getControl();
		}

		// konec zpracování
		$this->terminate();
	}
edke
Člen | 198
+
0
-

Ahoj David. Vdaka za postrcenie, uz mam zaklad, na com skusat Ajax. Funguje to, az na par typos, na ktore som narazil:

1. pri zmene lokality je treba pre druhy select aj zrusit disabled ako vo faze 1 tak 2:

	public function handleLoadData($phase, $value)
	{
$form = $this->template->form;

if ($phase == 1) {
	// naplníme select box prvky a vypíšeme na výstup
	$form['termin']
		->setItems( ... )
		->setDisabled(false);

2. pri zvoleni tretieho selectu treba enablovat submit, znovu typo:

// zvolena hodnota tretiho select boxu, povolí tlačítko submit
$('#frmform-submit1').attr('disabled', false);

Super, mozem sa pustit do Ajaxu :) Este raz vdaka za nakopnutie.

edke
Člen | 198
+
0
-

Este k tej obsluhe, je v Nette nato nejaka tovarnicka, ktora by pomahala tuto js obsluhu generovat priamo, alebo je to potrebne si to pisat samostatne v js ?

phx
Člen | 651
+
0
-

Technicka: tento formular nebude fungovat bez JS:( Jelikoz je tlacitko submit v HTML disabled. To by asi mel udelat az JS aby bez JS bylo mozne vybrat okalitu, odeslat, vybrat termin, odeslat atd…

Nebo se pletu?