zjištování změn hodnot ve formuláři

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

Ahoj,

prosím vás existuje nějaka metoda, která mi po odeslání formuláře řekne ano teď je změněné políčko.

Mám editaci udajů o uživateli už předvyplněnou:

xyzPresenter.php

//$rows['surname'] = Vořežprut; data vybrána z db
$form->addText('surname', 'Příjmeni')
     ->setDefaultValue($rows['surname']);

vyrenderuje se:

<input type="text" name="surname" value="Vořežprut">

po odeslání mi příjde:

$data = $form->getValues();
//$data['surname']; bude tu: Novák data poslaná uživatelem

$form->isChangedValue('surname');//vrátí true

Pač kdyby toto fungovalo tak nemusím přeukládat příjmení nebo nejaký data vytáhnout z db ověřit a zase uložit do db.

Předem děkuji

EDIT

Hodnoty nastavené setDefaultValue() se nemusí nijak posílat přes request, když se po odeslání opět pouští zpracovává ten stejný formulář jen je po odelaní budu mít s čím porovnat.

Editoval matata (10. 8. 2010 16:15)

Filip Procházka
Moderator | 4668
+
0
-

uložil bych asi výchozí data pro formulář do session a použil array_diff_assoc

Majkl578
Moderator | 1364
+
0
-

Jsem pro existenci nějaké metody, nejspíš přímo nad controlem, zrovna řeším stejný problém.

h4kuna
Backer | 740
+
0
-

HosipLan napsal(a):

uložil bych asi výchozí data pro formulář do session a použil array_diff_assoc

jako je to řešení pro tuto chvíli,

avšak se mi zdá zbytečný když nastavuju defaultní hodnoty tak není takový problém, aby si je framework uložil a pak porovnal.

Jak jsem psal nemusí se to ukládat do requestu když po odeslání probíhá opět ten samý nadefinovaný formulář a ty data se nemění které vytahnu z db, tak se znovu vytahnou a inicializujou

Editoval matata (10. 8. 2010 17:33)

Filip Procházka
Moderator | 4668
+
0
-

já naprosto souhlasím :)

Ondřej Mirtes
Člen | 1536
+
0
-

Tohle není bez použití sessions z principu možné.

Dostanu vyplněný formulář. Změním v něm nějaké hodnoty a odešlu. Jak by framework měl zjistit, které hodnoty tam byly předvyplněné? Pokud plnění výchozích hodnot provádíš v action* metodě, tak při novém requestu ten databázový dotaz na hodnoty proběhne znova a i kdyby si to formulář do momentu zpracování uložil někam vedle, nic neušetříš. Pokud setDefaults() voláš v render* metodě, tak formulář nemá v momentě zpracování o původních hodnotách ani páru.

Pokoušel jsem se něco takového implementovat před dvěma týdny a pohořel jsem. Nejjednodušší bude, pokud si ten původní záznam vytáhneš v submit metodě formuláře a ty hodnoty ručně porovnáš.

h4kuna
Backer | 740
+
0
-

Ondřej Mirtes napsal(a):

Tohle není bez použití sessions z principu možné.

ja bych řekl že to je možné, ono zaleží asi jak to máš naimplementované ja formuláře tvořím továrničkami a vidím co mi to dává a že ten dotaz je zase stejný, pac mam url klasicke <presenter>/<action>/<id> a to id tam je i po odeslani formulare, no dobře i kdyby to bral pomocí sessions, aby se to nedalo v url měnit id, avšak u článků mi to nevadí, tak si zapamatuje výchozí hodnoty

EDIT
detaily implementace bych nechtěl probírat spíše zda je to užitčné?

Každopádně když jsi se o něco pokoušel, Majkl578 taky a já jsme hledal něco takového, tak asi ano?

Editoval matata (10. 8. 2010 19:07)

David Grudl
Nette Core | 8142
+
0
-

Upřímně řečeno, neumím si představit, k čemu by to bylo dobré. Je snazší zavolat jeden UPDATE, než SELECT + ověřování isChangedValue + UPDATE, ne?

mlha
Člen | 58
+
0
-

Mám trochu podobný problém.
Formulář se sestavuje postupně. Po každém odeslání se přidají nová pole.
Protože je ale formulář už odeslaný, nefunguje u nových polí setDefaultValue().
To zjišťování změn by se taky hodilo, provedl by se pouze test klíčových form. prvků, které ovlivňují zobrazení podmíněných prvků.

h4kuna
Backer | 740
+
0
-

David Grudl napsal(a):

Je snazší zavolat jeden UPDATE, !než SELECT! + ověřování isChangedValue + UPDATE, ne?

Vyznačený SELECT není navíc stejně probíhá, šlo by jen o rozhodnutí zda update či nikoliv

Pomohlo by to v rozhodovaní další práce s daty které se nemusí vyplňovat.

redhead
Člen | 1313
+
0
-

+1

Panda
Člen | 569
+
0
-

Ondra Mirtes má pravdu, i moje konstrukce s formuláři vypadají nějak takto

protected function createComponentMyForm()
{
	$form = new AppForm();
	//...
	$form->onSubmit[] = callback($this, 'myForm_Submit');
}

public function myForm_Submit(Form $form)
{
	// ..
	$this->redirect('this');
}

public function renderDefault()
{
	$this['myForm']->setDefaults($model->find( ... ));
}

Metoda renderDefault se volá až po zpracování signálů, takže není s čím porovnávat změny. A feature, která v některých případech nemůže z principu fungovat (nastavování dat až v metodě render se mi jeví jako celkem běžná a logická praktika), mi nepřijde moc užitečná.

matata: v kódu, který jsem napsal, se při úspěšném odeslání formuláře ten vyznačený SELECT neprovede, byl by navíc.

mlha: na to nastavování výchozích hodnot u nových položek můžeš zkusit něco takového (píšu z fleku, tak možná budou nějaké překlepy):

FormControl::extensionMethod('forceDefaultValue', function (FormControl $control, $value) {
	if ($control->getValue() === NULL) {
		$control->setValue($value);
	}
});

// Doplnění: ještě dodám, že formulář by už v době sestavování měl být připojen k presenteru, jinak se po dodatečném připojení všechny hodnoty přepíší.

Editoval Panda (12. 8. 2010 21:58)

Ondřej Mirtes
Člen | 1536
+
0
-

Panda: Njn a právě, že se mi to nedařilo ani v action* metodě, loadHttpData nad jednotlivými prvky se volalo ještě před ní.

h4kuna
Backer | 740
+
0
-

Ondřej Mirtes + Panda: ok, když to bude přes session tak by to mohlo makat nějak takto
Nette a8c51dd released on 2010–07–23 pro php 5.2

kód nehodnotit :) s GITem nedělám a neumím takže tam je patch z svn a změněný soubory + příklad (example.php)

Panda
Člen | 569
+
0
-

Abychom předešli modifikacím formuláře, napsal jsem na to komponentu: https://gist.github.com/565891

//Doplnění: jen dodám, že je to zatím použitelné jen s AppForm.

Použtí je jednoduché:

	public function createComponentTestForm()
	{
		$form = new AppForm();

		// ...

		$form['tracker'] = new \NetteExtras\Forms\ChangeTracker();

		return $form;
	}

	public function testForm_Submit(Application\BaseForm $form)
	{
		\Nette\Debug::barDump($form['tracker']->getModifiedValues());
	}

Editoval Panda (5. 9. 2010 12:49)

Patrik Votoček
Člen | 2221
+
0
-

To se bude hodit…

h4kuna
Backer | 740
+
0
-

Panda napsal(a):

Abychom předešli modifikacím formuláře, napsal jsem na to komponentu: https://gist.github.com/565891

Přesně tak o toto mi šlo :)

Editoval matata (5. 9. 2010 12:31)

Panda
Člen | 569
+
0
-

Zkoušel jste tu komponentu někdo? Je to použitelné, nebo se to do addons ještě nehodí?

h4kuna
Backer | 740
+
0
-

Ahoj chtěl bych toto tema připomenout.
Teď jsem to opět potřeboval.

Přiklad:
mam výpis firem, které mají svoji tabulku a ke každé firmě můžu přidat 3 kontakty (jiná tabulka) a žádná hodnota není povinná, co kontakt to kontejner, bez ajaxu se mi všechny kontejnery zobrazují najednou. Když je formulář odeslaný, tak nechci prázdné řádky v db tak musím kontejnery kontrolovat a jejich hodnoty ručně jednu za druhou, zda uložit nebo neuložit.

Zavolat nad kontejnerem $form->getContainer(‚xxx‘)->isChanged(); by bylo fakt super. By mi to rozhodlo zda kontejner mam ulozit nebo uplne preskocit.

tzn INSERT || NOT INSERT nikoliv INSERT || UPDATE