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
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
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
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>