Pridani komponenty do formulare

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

potreboval bych do formulare „LogIn“ pridat komponentu „FieldUser“ kterou chci pouzit ve vice formularich, studoval jsem par prikladu a mam za to, ze by to melo fungovat tak jak to mam napsano nize, ale pise mi to error kteremu nerozumim:

Nette\InvalidStateException
Component ‚fieldUser‘ already has a parent.

<?php
use Nette\Application\UI\Form,
	Nette\Forms\Controls\TextInput,
	Nette\Security\AuthenticationException;

class CoursePresenter extends BasePresenter {

	public function createComponentFieldUser() {
		$field = new TextInput('Uživatel:', 20);
		$field->setRequired('Zadejte uživatelské jméno.')
			->addRule(Form::MIN_LENGTH, 'Uživatelské jméno musí mít nejméně %d znaků.', 5)
			->addRule(Form::MAX_LENGTH, 'Uživatelské jméno může mít maximálně %d znaků.', 10);
		return $field;
	}

	public function createComponentLogIn() {
		$fieldUser = $this->getComponent('fieldUser');
		$form = new Form;
		$form->addComponent($fieldUser, 'user');
		$form->addPassword('password', 'Heslo:')
			->setRequired('Zadejte heslo.');
		$form->addCheckbox('remember', 'Přihlásit trvale na tomto počítači');
		$form->addSubmit('send', 'Přihlásit');
		$form->onSuccess[] = callback($this, 'submitLogIn');
		return $form;
	}

	public function submitLogIn(Form $form) {
		....
	}
}
?>

Neporadil by nekdo kde mam chybu a jak to mam zapsat?

vvoody
Člen | 910
+
0
-

Urob si BaseForm (extends Nette\Application\UI\Form) a v nom si vytvor metodu:

public function addFieldUser($name = 'user', $label = 'Uživatel:', string $cols = 20, $maxLength = NULL){
	$field = new Nette\Forms\Controls\TextInput($label, $cols, $maxLength);
	$field->setRequired('Zadejte uživatelské jméno.')
		->addRule(Form::MIN_LENGTH, 'Uživatelské jméno musí mít nejméně %d znaků.', 5)
		->addRule(Form::MAX_LENGTH, 'Uživatelské jméno může mít maximálně %d znaků.', 10);
	return $this[$name] = $field;
}

potom uz len:

public function createComponentLogIn() {
	$form = new BaseForm;
	$form->addFieldUser();
	...
}
Martin Bubík
Člen | 13
+
0
-

diky za info, tvuj priklad je jen o malo slozitejsi nez moje reseni ktere taky funguje jak je popsano vyse, staci jen prepsat:

<?php
	public function createComponentLogIn() {
                $fieldUser = $this->getComponent('fieldUser');
		...
        }
?>

na

<?php
	public function createComponentLogIn() {
		$fieldUser = $this->createComponentFieldUser('fieldUser');
		...
	}
?>

s tim ze metoda createComponentFieldUser se muze jmenovat jinak, protoze se pouziva jako bezna funkce. Nicmene vic by se mi libilo kdyby to fungovalo jako normalni komponenta, tohle je takovy muj zkusebni projekt tak se to snazim naucit a pochopit, ale tohle mi nejde do hlavy proc to nefakci tak jak to mam napsano vyse. Kazdopadne diky za odezvu.

Editoval Martin Bubík (27. 6. 2012 20:20)

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Důvod, proč prvně uvedený příklad nefunguje, je ten, že komponenta fielfUser je automaticky připojena k instanci třídy, v níž je definovaná její továrnička – v tomto případě tedy k presenteru. Jak nad tím přemýšlím, možná je to klíčové uvědomit si, že metoda createComponent... je pouze továrničkou, sama ještě komponentu nedefinuje.

Řešením v tvém případě by bylo podědit si TextInput do třídy třeba FieldUser. A v továrničce formuláře pak nevolat getComponent(), ale přímo new FieldUser.

Martin Bubík
Člen | 13
+
0
-

Aha, tak to jsem nevedel, ze getComponent() mi to rovnou nekam pripojuje…
Mel jsem za to ze to udela teprve addComponent() nad objektem formulare.
Ted uz mi dava smysl ta chybova hlaska.

Chtel jsem se puvodne vyhnout tomu, vytvaret pro kazde pole samostatnou tridu, ale nakonec jsem to tak udelal jak si psal a ono to je asi opravdu logictejsi a porad lepsi nez opakovat stejny kod v ruznych formularich.

Dekuji za objasneni.

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Úplně na vysvětlenou – automatické připojení k rodiči proběhne hned po return $field;. Nette si totiž zjistí, jestli už je komponenta připojená, a pouze pokud ještě ne, provede automatické připojení na třídu obsahující továrničku. Viz Připojení komponenty k rodiči