Změna pořadí prvků ve formuláři při rozšíření vlastního formuláře

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Tomáš Votruba
Moderator | 1114
+
0
-

Mám vlastní formulářovou třídu loginForm (v ní inputy login, password a submit).
Chci přidat jeden input uprostřed, tím pádem ho ale automaticky dostanu na konec, za submit. To ne!

(Rád bych ho měl mezi pod password.)

Jde tento problém vyřešit bez ručního renderu?

Editoval Schmutzka (3. 4. 2012 22:46)

Jan Tvrdík
Nette guru | 2595
+
0
-

Mělo by to být řešitelné pomocí ručního volání nízkoúrovňové funkce addComponent s vyplněným třetím parametrem.

Tomáš Votruba
Moderator | 1114
+
0
-

Díky, teď mi ale vzniká dilema. Zmínění postup půjde v případě, kdy prvky vytvářím v __construct().
Já je ale vytvářím až v „attached“ https://api.nette.org/…orm.php.html#54, abych mohl využít settery pro nastavení např. délky hesla.

$form = new loginForm($this->user); // může být v configu, konstatní
$form->passwordLength = 10; // může být všude jiné, proto přes setter

Mohl bych sice ono číslo předat přes konstruktor, ale když mám těchto nastavitelných položek např. 10, bylo by to nepraktické.

Jak tedy mít možnost přidat prvek tam, kam potřebuji, a zároveň mít možnost využívat settery?

Ascaria
Člen | 187
+
0
-

Přečetl jsem si to několikrát, abych nenapsal nějakou odpověď úplně mimo, ale co třeba:

class loginForm
    {
    public function __construct($parent = null, $name = null)
        {
        parent::__construct($parent, $name);
	// tady je to už attachlé a tak můžeš "attached" mít už v konstruktoru
        }
    }

public function createComponentForm($name)
    {
    $form = new loginForm($this, $name, $this->user);
    $form->passwordLength = 10; // již attachlý form
    }

Editoval Ascaria (4. 4. 2012 1:18)

Tomáš Votruba
Moderator | 1114
+
0
-

@Ascaria: Jak by se v tomto případě aplikovala podmínka na délku hesla?

Jan Tvrdík
Nette guru | 2595
+
0
-

Nějak nechápu, v čem je problém. Proč by to v attached nemělo fungovat?

Ascaria
Člen | 187
+
0
-

@Schmutzka: Asi by to muselo prohledávat form a donastavovat takže ten setter by byl spíš jako normální metoda, než jen malý setter, máš pravdu je to blbost.

Tomáš Votruba
Moderator | 1114
+
0
-

Jan Tvrdík napsal(a):

Nějak nechápu, v čem je problém. Proč by to v attached nemělo fungovat?

Attached probíhá až při připojení k presenteru. Ještě před ní mohu využít právě settery. Jestli tomu zatím správně rozumím, pořadí je:

  1. __construct
  2. setters
  3. attached

Přičemž u 2) mohu přidat prkvy, ale zároveň ještě neexistují ty uvnitř třídy, které se vytvoří až ve 3). Proto nemůžu prvku v kroku 2) určit pořadí.

Napadlo mne obecné zadání, které snad k pochopení postačí.

Rozšiřuji loginForm a potřebuji:
1) přidat prvek mezi existující prvky
2) nastavit všechny položky jako povinné (zřejmě pomocí setteru)

Napadl mne pseudokód:

$form = new LoginForm;

// settery
$form->setter1 = TRUE;
$form->setter2 = TRUE;

// připojím prvky, které jsou v definované ve třídě
$form->attach();

// připojím prvky navíc a už si mohu vybrat kam
$form->addText("something", "Fill me:")

Editoval Schmutzka (4. 4. 2012 12:50)

Jan Tvrdík
Nette guru | 2595
+
0
-

Pořád nechápu problém. Dejme tomu, že nyní přidáváš prvek foo na konec takto.

$form->addText('foo');

Pokud chceš přidat prvek mezi prvky name a password, tak volání addText() nahradíš takto:

$component = new Nette\Forms\Controls\TextInput();
$form->addComponent($component, 'foo', 'password');
Tomáš Votruba
Moderator | 1114
+
0
-

Ano, to řeší bod 1) již od začátku. Zároveň potřebuji i bod 2), ptám se tedy jak to zkombinovat.

Uvnitř třídy loginForm je něco jako:

public function attached() {
	parent::attached();
	$this->addText("name", "Váše jméno, prosím");
	$this->addText("email", "Váš email, prosím");
	$this->addText("size", "Vaše velikost, prosím");
}

if($this->allRequired) { // dostanu přes setter
	$this["name"]->setRequired();
	$this["email"]->setRequired();
	$this["size"]->setRequired();
}
Tomáš Votruba
Moderator | 1114
+
0
-

Tak má idea potřebuje ještě jednu věc, existuje nějaký callback na toto?

$form = new LoginForm;
$form->addText("..."); // callback na pokus přidání control
davidm
Člen | 81
+
0
-

To asi neexistuje :) ale jestli ho potrebujes tak si poded form a pridej si ho do addComponent ne?

public function addComponent(Nette\ComponentModel\IComponent $component, $name, $insertBefore = NULL)
{
	$this->schmutzkovoCallback();
	parent::addComponent($component, $name, $insertBefore);
}
Tomáš Votruba
Moderator | 1114
+
0
-

davidm napsal(a):

To asi neexistuje :) ale jestli ho potrebujes tak si poded form a pridej si ho do addComponent ne?

public function addComponent(Nette\ComponentModel\IComponent $component, $name, $insertBefore = NULL)
{
	$this->schmutzkovoCallback();
	parent::addComponent($component, $name, $insertBefore);
}

To zní pěkně, ale chtěl bych to přímo pro addText, addSubmit etc., resp. pro první přidání prvku.
Tedy nejlépe v konstruktoru BaseControl (od kterého tyto třídy dědí), ale v rámci potomka třídy Forms, jinak bych musel všechny prvky nutit dědit můj BaseControl a to by bylo šílené.

revoke
Člen | 36
+
0
-

Schmutzka> podařilo se ti dospět k nějakému funkčnímu řešení?

Tomáš Votruba
Moderator | 1114
+
0
-

Jo, promiň, už jsem nedokončil myšlenku :).

Napsal jsem si medotu moveBefore, která umístí nový prvek tam, kam je potřeba. V něm se volá metoda build v níž jsou přidávány nové prvky. Je tedy zaručeno, že při pohybu je již formulář složen.
využije se v případě, kdy vytváříš samostatný formulář). Asi takto:

MyPresenter.php

protected function createComponentLoginForm()
{
	$form = new LoginForm;
	$form->passwordLength = 10;

	$form->addText("code", "Napiš 'code9'"); // připojím nový prvek
	$form->moveBefore("code", "login"); // přemístím úplně na začátek

	return $form;
}

Build u LoginForm.php může vypadat takto

Snad to je srozumitelné :).

revoke
Člen | 36
+
0
-

Částečné řešení problému zajistí použití addGroup() a SetCurrentGroup().