formulář – nezavolá se callback z onSuccess

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

Prosím o radu/kontrolu: jedná se o jednoduchý formulář s odesláním na email vytvořený uvnitř controlu.
Vykreslí se v pořádku, validace funguje v pořádku, když ho odešlu, data v $_POST jsou naplněná, ale callback nastavený v onSuccess se neprovede.

Určitě je to nějaká začátečnická blbost…

use Nette\Application\UI\Form;

class ContactFormControl extends \Nette\Application\UI\Control {

	public function render()
	{
	$form = new Form;
	$form->addText('name', 'Jméno:', 30, 40)
		->addRule(Form::MIN_LENGTH, 'Zadejte jméno', 5)
		->addRule(Form::MAX_LENGTH, 'Jméno může mít maximálně 40 znaků', 40);
	$form->addText('email', 'Váš email:', 30, 40)
		->addRule(Form::EMAIL, 'Zadaný email není platný.');
	$form->addTextArea('content', 'Text emailu:')
		->addRule(Form::MIN_LENGTH, 'Zadejte text emailu.', 10)
		->addRule(Form::MAX_LENGTH, 'Maximální délka textu je 5000 znaků', 5000);
	$form->addSubmit('send', 'Odeslat');
	$form->onSuccess[] = array($this, "sendSuccess");

	echo $form;
	}

	public function sendSuccess($form)
	{
		// tady se proste nic nestane
		$values = $form->getValues();
		die('sended');
		dump($values);
	}
}

Ještě doplním továrničku z presenteru ať je to kompletní:

protected function createComponentContactForm()
{
$c = new \ContactFormControl ();
return $c;
}
22
Člen | 1478
+
0
-

array bych nahradil metodou callback
edit: a hlavně bych dal form do továrny!!!

Editoval 22 (23. 8. 2011 15:06)

Filip111
Člen | 244
+
0
-

Nahrazení array callbackem nepomohlo (teď si vybavuji, že přesně tuhle radu jsem tu už někde viděl).

Můžeš prosím trochu rozvést tu továrnu – chápu smysl továrničky controlu v presenteru. Ty myslíš továrnu v controlu, v constructoru?
Díky.

Filip Procházka
Moderator | 4668
+
0
-

Fujky … ti to trochu upravim

class ContactForm extends Nette\Application\UI\Form {

        public function __construct()
        {
		parent::__construct();

		$this->addText('name', 'Jméno:', 30, 40)
			->addRule(Form::MIN_LENGTH, 'Zadejte jméno', 5)
			->addRule(Form::MAX_LENGTH, 'Jméno může mít maximálně 40 znaků', 40);
		$this->addText('email', 'Váš email:', 30, 40)
			->addRule(Form::EMAIL, 'Zadaný email není platný.');
		$this->addTextArea('content', 'Text emailu:')
			->addRule(Form::MIN_LENGTH, 'Zadejte text emailu.', 10)
			->addRule(Form::MAX_LENGTH, 'Maximální délka textu je 5000 znaků', 5000);
		$this->addSubmit('send', 'Odeslat');
		$this->onSuccess[] = array($this, "sendSuccess");
        }

        public function sendSuccess()
        {
                // tady se proste nic nestane
                $values = $this->getValues();
                die('sended');
                dump($values);
        }
}

a továrnička

protected function createComponentContactForm()
{
	return new \ContactForm();
}

Obalovat formulář do komponenty není špatný nápad, ale udělal jsi to úplně špatně. V metodě render se k němu signál nejenomže nedostane, ale vůbec jsi ten formulář ani nepřipojil k té rodičovské komponentě.

22
Člen | 1478
+
0
-

@HosipLan: myslel jsem, že to chce celé jako vykreslitelnou komponentu, ne jen extra třídu a renderování rešit až potom někde v šablonách…

Filip111
Člen | 244
+
0
-

@22: HosipLan už asi ví jak jsem na tom…takže nepředpokládá záludnosti, ale jen začátečnický chyby :)
Vykreslení je v šabloně jednoduše {control contactForm} a tohle je opravdu jen formulář. Možná to obalení controlem a nějakou další logikou budu potřebovat.

@HosipLan: Funguje to – myslel jsem, že pokud vytvářím komponentu musí dědit z \Nette\Application\UI\Control proto jsem se snažil formulář obalit. Teď mi ale docvaklo, že v továrničce createComponentContactForm() si vlastně můžu dělat co budu chtít.

Díky pánové, prozatím hotovo.

Filip Procházka
Moderator | 4668
+
0
-

@**Filip111**, 22: to udělat můžeš, ale nejjednodušší bude dát do šablony pohledu

{include 'mojeSablona.latte', 'form' => $control['contactForm']}

a tam v té „mojeSablona“ vykreslit ten formulář jak budeš potřebovat.

Pokud bys potřeboval můžeš formuláři časem upravit render metodu aby uměla vykreslit šablonu přímo.

22
Člen | 1478
+
0
-

@HosipLan: a bude na takovým formu fungovat AJAXová změna formu? viz. problém AJAX/snippety vs. {include *.latte}

Filip Procházka
Moderator | 4668
+
0
-

Řekl jsem nejjednodušší :) Ale dobrá poznámka, snippety fungovat nebudou a invalidace divně.

Filip111
Člen | 244
+
0
-

Prozatím se to chystám použít tak jak už jsem před pár dny diskutoval s HosipLan(em?)…mám v databázi texty, které se renderují do šablony. V textu může být použit nějaký control jakožto plugin, takže volání musí být co nejjednodušší.

Navíc incude tam prostě být nesmí, to už by byla megadíra v aplikaci.
Zatím ale nebudu předbíhat – až k tomu dojdu, začnu to řešit (a možná už budu chápat v Nette víc souvislostí, zatím je to kousek po kousku ale mám problém si to v hlavě pospojovat).

22
Člen | 1478
+
0
-

Navíc incude tam prostě být nesmí, to už by byla megadíra v aplikaci.

wtf?

Filip Procházka
Moderator | 4668
+
0
-

Něco mi říká, že jsi úplně mimo :)) include je naprosto v pořádku. Navíc tohle je include šablony, o tohle se stará Nette.

Ale možná jsem tě nepochopil, přeber si, co jsem napsal a zkus vysvětlit co jsi napsal ty.

Filip111
Člen | 244
+
0
-

Zkusím to rozvést…možná jsem úplně mimo, ale ještě nechci předbíhat :)

Převádím frontend staršího CMS, takže zrovna tohle je něco co by se v Nette dalo vyřešit líp…ale zatím nevím jak, takže myšlenku jsem převedl do Nette.

V DB mám uložené články, ty obsluhuje jeden presenter. Článek obsahuje text a protože si zákazník občas vzpomněl, že tady uprostřed textu chce mít anketu nebo že před kontaktním formulářem chce mít vlastní text, používám pro objekt ankety, kontaktního formuláře atd.

{control poll 1}
{control contactForm}

(Pokud tam toho je víc, článek se zamkne a edituji ho jen já, aby v tom lidi neudělali bordel)

V presenteru se pak tento text renderuje, takže komponenty se spustí a zobrazí. Žádoucí je, aby volání těchto komponent/pluginů bylo co nejjednodušší a aby v textu článku nemohlo být nic jiného než volání určitých komponent (například include).

Zatím nevím jak jinak bych podobné požadavky řešil…takže používám něco co asi není Nette řešení.
Jestli jste už pochopili o co mi jde a pořád si myslíte, že jsem úplně mimo, tak prosím o nástin jednoduchého Nette řešení (stačí jen myšlenka, bez kódu).

Díky.

Filip Procházka
Moderator | 4668
+
0
-

Aha, už tě chápu. Můžeš si udělat kombinaci maker, speciálně podle tvé potřeby. A třeba odstranit {include} a podobná, nebo naopak, povolit jen to co potřebuješ. Toto nastavené Latte Engine pak můžeš předat šabloně jako filtr a použít ji, pro zpracování textů.

Filip111
Člen | 244
+
0
-

Filtr zkusím – usnadnilo by mi to práci a zvýšilo bezpečnost.

22
Člen | 1478
+
0
-

…můžu prosím vědět, co to pořád plácáš o té bezpečnosti a magadírách v aplikaci? Nějak nechápu nebezpečnost include či defaultně nastavený latte Engine.

Editoval 22 (24. 8. 2011 10:37)

Filip111
Člen | 244
+
0
-

Vzhledem k tomu, že článek může editovat kde kdo, může tam klidně vložit sám nějaký latte makra a rozsypat design, případně při použití neexistujícího controlu to spadne do chyby.
Nekoukal jsem, jak Nette ošetřuje include v šablonách – pravděpodobně je to ošetřené, takže by to nemusela být bezpečnostní díra narozdíl od klasického includu, ale při zadání neexistujícího includu by to stejně skončilo chybou celé aplikace.

Pointa je zkrátka taková, že je nežádoucí aby uživatel, který tvoří články používal jakákoliv latte makra s výjimkou povolených controlů.

Asi by nakonec bylo lepší, kdybych nezapisoval do článků přímo volání controlu, ale jen nějaké zástupné znaky, např.:

[[plugin poll 1]]

a obsah článku držel striktně v rovině HTML a nepovoloval jiné elementy.
Potom bych před vypsáním nahradil tyto volání pluginu za volání controlu {control poll 1} a nechal renderovat obsah.

Filip Procházka
Moderator | 4668
+
0
-

Článek v databázi preprocesuje pomocí latte, aby v něm mohl mít vykreslení komponent (třeba anketu). Proto je nežádoucí, aby redaktor mohl napsat {include 'sablona'}, nebo nejdeboze

{? dump(Nette\Environment::getConfig())}

Ještě bys mohl udělat to, že by jsi využil Texy! a dopsal si do něj modul, který tohle zpracuje, nějaký výchozí na metadata {{neco}} tam už je, snad by šel upravit?

Editoval HosipLan (24. 8. 2011 11:17)

22
Člen | 1478
+
0
-

jo, už mi to docvaklo, o co Filipovi jde..

Lopata
Člen | 139
+
0
-

Hlavně je třeba mít na paměti, že Latte neodstraňuje php tagy, to musíš udělat sám. K čemu je zakázané {include $dest}, když funguje normálné PHP include, že… Doporučuji podědit Nette\Latte\Engine a přepsat metodu __invoke(). Budeš-li to odstraňovat regulárním výrazem, dej pozor na vylomeniny typu <<?php ?>?php foo(); ?> nebo <?php foo(); /* (žádný end tag). Neopomeň ani asp a short tags, popř. <?=.

Filip111
Člen | 244
+
0
-

Texy asi používat nebudu – v administraci používám TinyMCE, takže si přegenerování nějakých metadat budu muset zajistit sám.
Jde o to, že zatím mám předělaný jen frontend a ten využívá již existující strukturu databáze – nebyl jsem nucenej nic měnit, takže můžu kdykoliv nakopírovat novou verzi frontendu v Nette na starší web (vlastní „CMS“) kde jsou již články v DB uložený v HTML formátu (udělat update struktury databáze na aktuální verzi), lehce upravit šablony (což ze Smarty na latte není takový problém) a web by měl běžet jako dřív (tedy lépe než dřív :)

Pokud zjistím, že musím udělat tlustou čáru mezi starou a novou verzí frontendu nebo celého CMS, změnit strukturu DB a hlavně až budu mít pod Nette udělanou i administraci, můžu uvažovat o používaní Texy!

@Lopata: díky za rady…když už jste mi toho všichni tolik doporučili, asi se do toho pustím co nejdřív.

Editoval Filip111 (24. 8. 2011 13:15)