Disabled pole na základě vyplnění jiného pole

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

Zdravím.

Mám formulář, který používám pro přidání nového i úpravu stávajícího uživatele.
Obsahuje skryté pole id, které rozhoduje, zda se uživatel přidává nebo upravuje. Potřeboval bych i na základě tohoto pole nastavit disabled pole login, ale netuším, jak to udělat.

Avalakazar
Člen | 3
+
0
-

Nejjednodušší způsob je přes session, v metode presenteru pro vytvoreni komponenty

<?php
...
$session = NEnvironment::getSession("tvojeaplikace");
$id = $session->selected_id;

if($id) {
	$login->getControl()->setDisabled();
}
...
?>

Při uložení uživatele, vybrání jeho id do session zapíšeš.

<?php
$session = NEnvironment::getSession("tvojeaplikace");
$session->selected_id = $id;
?>
Jan Tvrdík
Nette guru | 2595
+
0
-
$form->addText('login')->setDisabled($form['id']->getValue() === NULL)
Lawondyss
Člen | 106
+
0
-

Jan: Něco podobného mě napadlo hned na začátku, ale nefungovalo to. Ani tohle nefunguje :(
Možná by to mohlo být tím, že výchozí hodnoty v případě editace se plní při renderu:

public function renderEdit($id)
{
  $this->template->id = $id;

  // pokud jde o upravu
  if($id)
  {
    // nastaveni vychozich hodnot
    $this->getComponent('formEdit')->setDefaults($this->users->getUser($id));
  }
}
Filip Procházka
Moderator | 4668
+
0
-

ne, problém je v tom, že nepřipojuješ formulář pomocí konstruktoru

takhle

protected function createComponentMyForm($name)
{
	$form = new Nette\Application\AppForm($this, $name);

	// ...
	$form->addText('login')->setDisabled($form['id']->getValue() === NULL)
	// ...

}

ale děláš to takhle

protected function createComponentMyForm()
{
	$form = new Nette\Application\AppForm;

	// ...
	$form->addText('login')->setDisabled($form['id']->getValue() === NULL)
	// ...

	return $form;
}

žejo? :)

Lawondyss
Člen | 106
+
0
-

HospiLan: Nee, dělám to jak by se mělo.

	public function createComponentFormEdit($name)
	{
		$form = new AppForm($this, $name);

		$form->setTranslator($this->trans);

		$form->addHidden('id');

		$form->addCheckbox('active', 'Aktivní');
		$form->addText('login', 'Login', 25, 15)
				->addRule(Form::FILLED, 'Vyplňte Login.');

		$form->addText('name', 'Jméno', 25, 40)
				->addRule(Form::FILLED, 'Vyplňte Jméno.');
		$form->addSelect('position', 'Pozice', $this->roles)
				->skipFirst('-- vyberte --')
				->addRule(Form::FILLED, 'Vyberte Pozici.');
		$form->addPassword('password', 'Heslo', 25)
				->addConditionOn($form['id'], ~Form::FILLED)
					->addRule(Form::FILLED, 'Vyplňte Heslo.');
		$form->addPassword('password_repeat', 'Heslo znova', 25)
				->addConditionOn($form['password'], Form::FILLED)
					->addRule(Form::EQUAL, 'Hesla se musí shodovat.', $form['password']);
		$form->addSubmit('send', 'Odeslat');
		$form->addSubmit('back', 'Zpět')
				->setValidationScope(FALSE)
				->onClick[] = array($this, 'CancelClicked');

		$form->onSubmit[] = array($this, 'submittedFormEdit');

		// zavola obsluzne handlery
		$form->fireEvents();

		return $form;
	}
Filip Procházka
Moderator | 4668
+
0
-
	// zavola obsluzne handlery
$form->fireEvents();

tohle dělat vubec nemusíš

a kde máš to setDisabled?

Lawondyss
Člen | 106
+
0
-

HospiLan: Odstranil jsem ho, protože nefunguje. Ale měj jsem ho takto:

	public function createComponentFormEdit($name)
	{
		$form = new AppForm($this, $name);
		//...
		$form->addText('login', 'Login', 25, 15)
				->addRule(Form::FILLED, 'Vyplňte Login.')
				->setDisabled($form['id']->getValue() === NULL);
		//...

		return $form;
	}
Chbox
Člen | 125
+
0
-

a co je v téhle hodnotě?

$form['id']->getValue() === NULL

potřebuješ, aby tam bylo TRUE, jinak tam je asi FALSE a tím pádem se disabled nekoná..

Filip Procházka
Moderator | 4668
+
0
-

samozřejmě to funguje, špatně to voláš

$control->setDisabled(!$form['id']->getValue());
Jan Tvrdík
Nette guru | 2595
+
0
-

Tady snad všichni myslí kolenem :) Tak jednoduchý problém a tolik špatných návrhů. Následující 3 návrhy by měly fungovat.

class FooPresenter1
{
	public function renderEdit($id)
	{
		if ($id !== NULL) {
			$form = $this['formEdit'];
			$form['login']->setDisabled();
			$form->setDefaults($this->users->getUser($id)); // TODO: Zkontrolovat, zda daný uživatel existuje!
		}

		$this->template->id = $id;
	}
}

class FooPresenter2
{
	/** @var ??? */
	private $user;

	public function actionEdit($id)
	{
		if ($id !== NULL) {
			$this->user = $this->users->getUser($id); // TODO: Zkontrolovat, zda daný uživatel existuje!
		}
	}

	public function renderEdit($id)
	{
		$this['formEdit']->setDefaults($this->user);
		$this->template->id = $id;
	}

	protected function createComponentFormEdit($name)
	{
		...
		$form->addText('login')
			->setDisabled($this->user !== NULL);
		...
	}
}

class FooPresenter3
{
	protected function createComponentFormEdit($name)
	{
		...
		$form->addText('login')
			->setDisabled($this->getParam('id') !== NULL);
		...
	}
}
Lawondyss
Člen | 106
+
0
-

Jan: Díky, to zabralo. Předpokládám, že stejným způsobem je nutné řešit přidání kontrolní podmínky. Při editaci totiž Login neprojde PHP validací (žádný se neodeslal).

toka
Člen | 253
+
0
-

No, a jak moc velká „prasárna“ by bylo, kdybys loginu přidal atribut readonly, pak se validační pravidlo provede a při zpracování formuláře při editaci pak $formValues = $form->getValues(); unset($formValues['login']);? Pokud to chápu dobře, tak na sestavevní UPDATE dotazu používáš jako PK id. Tzn. že i kdyby uživatel jakkoliv login i přes readonly podvrhl, nemusí tě to vůbec zajímat.

Lawondyss
Člen | 106
+
0
-

Toka: Prasárna asi žádná a ulehčilo by mě to práci, ale obecně nemám readonly rád. Políčko se tváří jako že je editovatelné, ale prostě není. Což může být pro méně zkušeného uživatele horor, protože nějaké readonly vůbec nezná.

Jan Tvrdík
Nette guru | 2595
+
0
-

Lawondyss napsal(a):

Předpokládám, že stejným způsobem je nutné řešit přidání kontrolní podmínky. Při editaci totiž Login neprojde PHP validací (žádný se neodeslal).

Na disabled inputech se validace vůbec nespouští. Samotná skutečnost, že se validace spustila znamená, že v době jejího spuštění ještě neproběhlo zablokování daného inputu.

Vyjdu-li z předpokladu, že není chyba v Nette (to se mi teď nechce ověřovat), tak to znamená, že jsi z mnou nabízených řešení použil první, které jako jediné provádí zablokování inputu až po spuštění validace. Řešením je tedy použít řešení (2), (3) nebo upravit řešení (1) (renderaction)

Lawondyss
Člen | 106
+
0
-

Jan: Díky. Přesunutí řešení problému do action zabralo.