Vlastné formulárové pole: $form->addCancel

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

Ahoj. Rád by som si rozšíril AppForm o vlastné pole.

Namiesto tohoto:

<?php
    $form->addButton('cancel', 'Zrušiť');
?>

by som rád:

<?php
    $form->addCancel('Zrušiť');
    $form->addCancel('Zrušiť', $link);
?>

ktorý by však negeneroval button, ale čosi takéto:

<div class="cancel"><a href="{link ...}">{$text}</a></div>

kde link bude odkazovať na aktuálny view (formulár bez zadaných údajov), alebo na linku z argumentu $link.

Ako na to? (v models/ pridať novú triedu Formular extends AppForm, v ktorej si vytvorím addCancel… Tá metóda bude robiť čo? Kam dám template? Potrebujem vôbec template/dá sa to vygenerovať priamo z PHP?)

Vďaka za pomoc.

saimons
Člen | 293
+
0
-

mozna by ti pomohlo toto: rocni vykresleni formulare, nebo pridani html ke generovanemu objektu formulare: https://forum.nette.org/…do-formulare

ezimir
Člen | 21
+
0
-

saimons napsal(a):

mozna by ti pomohlo toto: rocni vykresleni formulare, nebo pridani html ke generovanemu objektu formulare: https://forum.nette.org/…do-formulare

Pridanie ľubovoľného HTML k objektu je síce pekné ale:

  • týmto som chcel neskôr riešiť aj iné objekty, nie len addCancel
  • cancel má význam pri addSubmit, avšak nasledovné nevygeneruje <a> (funguje mi to s addText, ale tam to nie je relevantné):
<?php
    $form->addSubmit('submit', 'Poslať');
    $form['submit']->setOption('description', Html::el('a href=...')->setText('Zrušiť'));
?>

Pokiaľ si ma chcel odkázať na Makra pro „ruční“ vykreslování formulářů, tak to je jednak overkill, a druhak nechcem si „zašpiniť“ šablóny <a href="">-mi všade kde to budem potrebovať.

Jak přidat do formuláře <button> sa dozvedám, že:

Šaman napsal(a):

Takze input je cistejsi a spolehlivejsi, o coz v Nette jde. Ale myslim, ze jde predefinovat, co vlozi metoda addButton() do formulare pomoci

<?php
$form['controlName']->getControlPrototype();
//Nette\Web\Html objekt, na něm můžeš dělat, co chceš
?>

Tam si síce vytvorím HTML aké len chcem, ale pretváranie napríklad addButton input-u na <a href> mi príde neslušné.

Ehm, cestou vlastného AppForm sa teda nedá ísť? Chcem od Nette príliš veľa?

bazo
Člen | 620
+
0
-

tak na to si musis vytvorit vlastny formularovy prvok

Filip Procházka
Moderator | 4668
+
0
-

Vlastní formulářový prvek není zrovna nejlepší řešení.

Viděl bych to buď

  • pomocí ručního renderování a tudíž ručně zapsat html
  • nebo tlačítko
$form->addSubmit('cancel', 'Zrušit')->onClick[] = function(Nette\Forms\IFormControl $control) {
	$control->form->presenter->redirect('nekam:jinam');
}; // zbytečné na to dělat vlastní metodu, ne?

// můžeš si klidně přestylovat tlačítko aby vypadalo jako odkaz
$form['cancel']->getControlPrototype()->class('fakelink');
ezimir
Člen | 21
+
0
-

HosipLan napsal(a):

Vlastní formulářový prvek není zrovna nejlepší řešení.

Prečo? Za/proti? Mne osobne sa tento variant pozdáva najviac, len neviem presne ako na to…

Viděl bych to buď

  • pomocí ručního renderování a tudíž ručně zapsat html
  • nebo tlačítko
$form->addSubmit('cancel', 'Zrušit')->onClick[] = function(Nette\Forms\IFormControl $control) {
	$control->form->presenter->redirect('nekam:jinam');
}; // zbytečné na to dělat vlastní metodu, ne?

onClick… toto je super vec, vďaka!

// můžeš si klidně přestylovat tlačítko aby vypadalo jako odkaz
$form['cancel']->getControlPrototype()->class('fakelink');

Toto je samozrejme funkčné, len by som sa rád vyhol „pretvarovaniu button-u ako linky“, kedže to sú dva rozdielne elementy (a veci, ktoré majú reprezentovať sú teoreticky presne opačné (primary/secondary form action)). Tým, že by som použil vlastný formulárový prvok, by som sa vyhol písaniu viacerých riadkov v každom formulári kde by som to potreboval, alebo si tento modifikovaný prvok viem nejak „odložiť“?

Editoval ezimir (7. 12. 2010 21:46)

Filip Procházka
Moderator | 4668
+
0
-

ad. $form->addSubmit():
asi se ti ještě bude hodit ->setValidationScope(FALSE)

$form->addSubmit('cancel', 'Zrušit')
	->setValidationScope(FALSE) // vypne validaci! v tomhle případě docela důležité ;-)
	->onClick[] = function(Nette\Forms\IFormControl $control) { // po kliknutí následuje přesměrování
		$control->form->presenter->redirect('nekam:jinam');
		// tady už se nevykonají akce z $form->onSubmit;
	};

ad. fakelink:

$form['cancel']->getControlPrototype()->class('fakelink');

přidá tlačítku <input type="submit" name="cancel"> jednoduše atribut class="fakelink" a ty si ho nastyluješ.

ad:

ezimir napsal(a):

Prečo? Za/proti? Mne osobne sa tento variant pozdáva najviac, len neviem presne ako na to…

  • je to zbytečné
  • Nette\Forms\DefaultFormRenderer zpracovává pouze IFormControl prvky a pod ně odkaz moc nespadá, že. (je to jen o logice, implementovat by to problém být neměl)

ale když už tak asi zápis

$form->addCancel('cancel', 'Zrušit', 'nekam:jinam'); // nebude úplně od věci

otázkou je jak moc se to vyplatí, když kód který dělá to stejné je o tři řádky delší…
Rozhodně bych to ale nedrátoval jako odkaz, ten totiž není prvkem formuláře. Ale pokud si to moc přeješ nic moc by ti v tom bránit nemělo :)

Editoval HosipLan (7. 12. 2010 22:19)

ezimir
Člen | 21
+
0
-

HosipLan napsal(a):

ad. fakelink:

$form['cancel']->getControlPrototype()->class('fakelink');

přidá tlačítku <input type="submit" name="cancel"> jednoduše atribut class="fakelink" a ty si ho nastyluješ.

Preštýlovať button aby vyzeral ako a, hmmm, to mi je proti srsti (text-decoration: underline na buttone?).

ad:

ezimir napsal(a):

Prečo? Za/proti? Mne osobne sa tento variant pozdáva najviac, len neviem presne ako na to…

  • je to zbytečné
  • Nette\Forms\DefaultFormRenderer zpracovává pouze IFormControl prvky a pod ně odkaz moc nespadá, že. (je to jen o logice, implementovat by to problém být neměl)

Takže si viem vytvoriť vlastný FormControl, ktorý mi DefaultFormRenderer zobrazí? Takto nejako?

<?php
    class Cancel extends FormControl {
        public function __construct($title, $href) {
            parent::__construct(NULL);
            $this->control->type = 'link';
            $this->title = $title;
            $this->href = $href;
        }

        public function getControl() {
            return Nette\Web\Html::el('a href='.$this->href)
                ->setText($this->title);
        }
    }

    // ...

    $form[$name] = new Cancel($title, $href);
?>

Dá sa nejako rozumne modifikovať DefaultFormRenderer (renderBody, $wrappers, …) tak, aby podľa $control->type vygeneroval <a>? Pretože link obalený v table > tr > td je zbytočnosť. (rozumne = nepísať celý vlastný form renderer)

ale když už tak asi zápis

$form->addCancel('cancel', 'Zrušit', 'nekam:jinam'); // nebude úplně od věci

otázkou je jak moc se to vyplatí, když kód který dělá to stejné je o tři řádky delší…
Rozhodně bych to ale nedrátoval jako odkaz, ten totiž není prvkem formuláře. Ale pokud si to moc přeješ nic moc by ti v tom bránit nemělo :)

HTML overwrite riešenie:

To oštýlovanie sa dá oblbnúť s trikom z Jak přidat do formuláře <button>, ale keď už priamo HTML tak lepšie nasledovne (nejaké tipy ako toto ešte zjednodušiť?):

<?php
    class MyForm extends AppForm {
        public function addCancel($name, $title, $href) {
            $this->addButton($name, NULL);
            $html = $this[$name]->getControlPrototype();
            $html->setName('a href="' . $href . '"');
            $html->type = NULL;
            $html->add($title);

            return $this[$name];
        }
    }

    class TestPresenter extends BasePresenter {
        protected function createComponentNazevFormu() {
            $form = new MyForm;
            $form->addCancel('cancel', 'Zrušiť', $this->link(':Homepage:default'));
            return $form;
	}
}
?>
JakubJarabica
Gold Partner | 184
+
0
-

ezimir napsal(a):
Preštýlovať button aby vyzeral ako a, hmmm, to mi je proti srsti (text-decoration: underline na buttone?).

Imho tvoje riešenie je overkill. Snažíš sa simulovať funkcionalitu formulárového buttonu(odkaz „riadiaci“ form mi nepríde sémantické – button áno), na ktorý ide krásne navešať onclick event podľa potreby s pár riadkami kódu.

ezimir
Člen | 21
+
0
-

JAM3SoN napsal(a):

ezimir napsal(a):
Preštýlovať button aby vyzeral ako a, hmmm, to mi je proti srsti (text-decoration: underline na buttone?).

Imho tvoje riešenie je overkill. Snažíš sa simulovať funkcionalitu formulárového buttonu(odkaz „riadiaci“ form mi nepríde sémantické – button áno), na ktorý ide krásne navešať onclick event podľa potreby s pár riadkami kódu.

  1. http://files.myopera.com/…te-forum.png
  2. Prečo „simulovať funkcionalitu formulárového buttonu“ a nie „formulárového prvku“? Aj link môže byť súčasťou formulára, čo Ti na ňom nepríde sémantické? (Ono ten link form neriadi (v mojom prípade), pretože s ním ani nenapredujem, ani sa nevraciam k niektorému z predošlých stavov formulára. Idem od začiatku, čo IMHO nie je v súvislosti s predošlou interakciou s formulárom).
  3. http://www.lukew.com/…Sactions.asp (a o trošku menej relevantné http://www.svennerberg.com/…n-web-forms/)
  4. Všade kde môžem/viem sa snažím formulárové prvky, ktoré nevedú k úspešnému ukončeniu vyplnenia diametrálne odlíšiť od tých, ktoré áno… Veľmi účinné je použitie <a href>… nejaké tipy ako na to v Nette?
Filip Procházka
Moderator | 4668
+
0
-

Rozhodně je hloupost použít jako základ FormControl, bude ti to vytvářet další prvek v odeslaných datech formuláře. Možná, nestudoval jsem, lepší je použít nějakou třídu co je na tlačítko, nebo si vytvořit vlastní a implementovat IFormSubmitter. V obou případech však jde o to, že porušuješ rovnost, kde na jedné straně je strom komponent ve formuláři (FormContainery a IFormControly) a na druhé straně jsou prvky ve stránce, které se ti promítnou do POST dat. Což, jak jsem jsem říkal, může dělat neplechu s formuláři, ale nestudoval jsem to tak moc, ale co si pamatuji tak k tomu jsou formuláře laxní, tak snad by to z technické stránky vadit moc nemělo (hrozná věta :D).

Čistější je ->onClick[] = function($control){ ... } nebo ruční render

ad. $this->link(): Lze to udělat i lépe

$form->addCancel('cancel', 'Zrušiť', new Nette\Application\Link($this, ':Homepage:default'));

což je vpodstatě lazy obálka, která ti vytvoří odkaz, až když je potřeba
(ale v tvém případě to asi nevyužiješ, takže to ber jako perličku;)

<?php
/* PS: */ $html->setName('a href="' . $link . '"'); // tohle je strašně hnusný hack!
ezimir
Člen | 21
+
0
-

HosipLan napsal(a):

Rozhodně je hloupost použít jako základ FormControl, bude ti to vytvářet další prvek v odeslaných datech formuláře. Možná, nestudoval jsem, lepší je použít nějakou třídu co je na tlačítko, nebo si vytvořit vlastní a implementovat IFormSubmitter. V obou případech však jde o to, že porušuješ rovnost, kde na jedné straně je strom komponent ve formuláři (FormContainery a IFormControly) a na druhé straně jsou prvky ve stránce, které se ti promítnou do POST dat. Což, jak jsem jsem říkal, může dělat neplechu s formuláři, ale nestudoval jsem to tak moc, ale co si pamatuji tak k tomu jsou formuláře laxní, tak snad by to z technické stránky vadit moc nemělo (hrozná věta :D).

Aaaaaha! Pridávať ďalší prvok na odoslanie, ktorý nikdy nepoužijem je fakt blbosť.

Čistější je ->onClick[] = function($control){ ... } nebo ruční render

ad. $this->link(): Lze to udělat i lépe

$form->addCancel('cancel', 'Zrušiť', new Nette\Application\Link($this, ':Homepage:default'));

Super!

což je vpodstatě lazy obálka, která ti vytvoří odkaz, až když je potřeba
(ale v tvém případě to asi nevyužiješ, takže to ber jako perličku;)

<?php
/* PS: */ $html->setName('a href="' . $link . '"'); // tohle je strašně hnusný hack!
?>

To teda je… ale pozdáva sa mi viac ako ručný render… zatiaľ…

Vďaka za pomoc.