Závislé select boxy a setRequired

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

Ahoj,

stále mi nedá pokoj, ako vyriešiť závislé select boxy v nette. Čítal som návod na planette, ale moc sa mi nepáči. Nerieši ak potrebujem formulár používať aj ako editačný a konzistenciu dát.

Ako vyriešiť overenie, že id subkategórie patrí naozj nadradenej kategórii? Ak použijem $form->httpData užívateľ mi tam može podstrčiť hocičo a nemožem použiť setRequired pretože select box nemá po odoslaní položky.

David Matějka
Moderator | 6445
+
0
-

Jo, taky se mi to nelibi. Ja to resim tak, ze mam podedeny select box a pridany event, ktery upozornuje na zmenu hodnoty.
Zkracene nejak takhle:

class MySelectBox extends Nette\Forms\Controls\SelectBox
{
	/** @var array of function(self, $newValue, $oldValue) */
	public $onChange = [];


	public function setValue($value)
	{
		$oldValue = $this->getValue();
		parent::setValue($value);
		$this->onChange($this, $value, $oldValue);

		return $this;
	}


	public function loadHttpData()
	{
		$oldValue = $this->getValue();
		parent::loadHttpData();
		$this->onChange($this, $this->getValue(), $oldValue);
	}
}

a pouziti zhruba:

$form['country'] = new MySelectBox(...);
$city = $form->addSelect('city');
$form['country']->onChange[] = function ($control, $newValue) use ($city) {
	$city->setItems($this->getCitiesByCountry($newValue));
};
japlavaren
Člen | 404
+
0
-

Tak zatiaľ jediné „čisté“ riešenie, ktoré som objavil je toto:

<?php
class SearchForm extends UI\Control
{
	public $values = array();


	public function render()
	{
		/** @var Form $form */
		$form = $this['form'];

		$form['categoryId']->controlPrototype->{'data-load-subcategories'} = $this->link('loadSubcategories!', array('categoryId' => 'CATEGORY_ID'));

		if(!$form->isSubmitted()){
			$this->loadSubcategories($this->values['categoryId']);

			$form->setDefaults($this->property + array('brokerId' => $this->brokerId));
		}

		$this->template->setFile(__DIR__ . '/template.latte');
		$this->template->render();
	}


	protected function createComponentForm()
	{
		$form = new UI\Form;

		$form->addSelect('categoryId', 'Category', $this->categoryModel->getCategories())
			->setPrompt(' - select category - ')
			->setRequired('Please select category.');

		$form->addSelect('subcategoryId', 'Subcategory');

		$form->addSubmit('send', 'Send');

		$self = $this;
		$form->onSuccess[] = function (Form $form) use ($self) {
			$data = $form->getHttpData();

			$self->loadSubcategories($data['categoryId']);
			$self->loadDistricts($data['provinceId']);

			$form->validate();
		};

		$form->onSuccess[] = $this->processForm;

		return $form;
	}


	public function processForm(UI\Form $form, $values)
	{
		dump($values);
	}


	public function handleLoadSubcategories($categoryId)
	{
		$this->loadSubcategories($categoryId);

		$this->presenter->sendResponse(new TextResponse($this['form']['subcategoryId']->getControl()));
	}


	public function loadSubcategories(&$categoryId) // public visibility considering using in callback
	{
		if ($items = $this->subcategoryModel->getSubcategories($categoryId)) {
			$this['form']['subcategoryId']->setPrompt(' - select subcategory - ')
				->setItems($items)
				->setRequired('Please select subcategory.');
		}
	}
}
?>
<script>
$(function(){
	var form = $('form');

	form.on('change', 'select[name=categoryId][data-load-subcategories]', function () {
		var category = $(this);
		var subcategory = category.closest('form').find('select[name=subcategoryId]');
		var url = category.data('load-subcategories').replace('CATEGORY_ID', category.val());

		$.ajax(url).success(function (data) {
			subcategory.replaceWith(data);
		});
	});
});
</script>