Dependency select AJAX v includovaném formuláři
- argosovo
- Člen | 54
Ahoj,
mám dva dotazy – poté co se několik dní snažím skamarádit s AJAXem ve
formuláři v nette. Nakonec bych potřeboval vytvořit 4 selecty (zatím jsou
zkušebně dva) – kdy každý select po výběru přes ajax načte data pro
select následující (ten první samozřejmě může načíst data už při
vytvoření formuláře) → ve smyslu
Typ->značka->model->podkategorie. Dva problémy které
v tom vidím:
- pročetl jsem a vyzkoušel nesčetně způsobů jak zaručeně dostat ajax do formuláře v nette – díky tomu mám celý kód plný zakomentovaných pokusů a nepotřebných proměnných – tady proto uvádím snad původní jednoduchou neupravenou verzi která zobrazí vše bez chyb – nic z toho však nešlo – předpokládám, že je to tím, že mám formulář ve vlastním souboru s vlastní šablonou – je někde návod, který opravdu funguje na tuto situaci – pokud bych si mohl vybírat ideálně s jquery na obsluhu ajaxu
- při načítání hodnot selectu bych potřeboval mít přístup do modelu, tedy aby model dodal potřebná data do selectu – v presenteru to funguje, ale uvnitř formuláře už ne(inject modelu je asi pozdě, při konstrukci formuláře tam posílám $this,$name a ne odkaz na daný model) – co s tím?
Takže prozatím to co mi funguje a otázka je jak to rozšířit?
HomepagePresenter.php
<?php
protected function createComponentHledaniMain($name)
{
$form = new \App\FrontModule\Forms\HledaniMain($this,$name);
return $form;
}
?>
Dále mám zmíněný formulář HledaniMain (tady bych nejraději řešil obsluhu Ajaxu – aby z formuláře byla soběstačná jednotka kterou presenter vloží a dál se o ní nestará):
<?php
class HledaniMain extends \Nette\Application\UI\Control
{
private $select,$form;
public function render()
{
$template = $this->createTemplate();
$template->setFile(__DIR__ . '/templates/hledaniMain.latte');
$template->registerFilter(new \Nette\Latte\Engine());
$template->render();
}
private function setSelect(){
//tady se nějakým způsobem vytvoří data do selectu, pro úplnost předpokládejme následující
$this->select=$data;
}
public function createComponentHledaniMain(){
$this->form = new \Nette\Application\UI\Form;
$this->setSelect();
$this->form->addSelect('kind', 'Druh', $this->select);
$this->form->addSelect('mark', 'Vyberte druh')
->setPrompt('...');
$this->form->addSubmit('search', 'Vyhledat')
->onClick[] = callback($this, "formSucceeded");
return $this->form;
}
public function formSucceeded(\Nette\Forms\Controls\SubmitButton $button) {
$values = $button->getForm()->getValues();
}
}
?>
Dále taky šablona hledaniMain.latte (do budoucna bude složitější proto to celé dělám):
<?php
{form hledaniMain}
{input kind}<br />
{snippet mark}
{input mark}<br />
{/snippet}
{input search}
{/form}
?>
Editoval argosovo (17. 12. 2014 13:49)
- karelu
- Člen | 14
Ahoj,
zkus se podívat na řešení od Martina Zlámala, možná Ti to pomůže
nasměrovat:
http://www.zeminem.cz/…t-select-box
- argosovo
- Člen | 54
Ahoj,
po delší odmlce uvádím funkční řešení na které jsem přišel po
nesčetně nefunkčních pokusech… Formulář jsem prvně rozchodil dle
návodu výše – děkuji, následně jsem chtěl přesunout formulář do
komponenty která mi generuje formulář a rozšiřuje
\Nette\Application\UI\Control – tak aby šla formuláři nastavit šablona.
Následně cokoliv jsme v šabloně obalil makrem snippet hlásilo se jako
neexistující komponenta. To co se bohužel nikde nepíše, nebo spíš
člověk neví, že to má hledat je, že „Všechny prvky
v komponentě musí mít jméno směrované do komponenty.“ (ano,
pro zkušenější nebo pro ty co si tím prošli asi naprosto jasná informace,
pro začátečníka jako já minimálně dva týdny pokusů proč to pořád
nejde – moje componenta se jmenuje hledaniMain takže si
všímejte zejména toho, kde všude musí být tento název uveden aby to
fungovalo) takže v šabloně:
<?php
{form hledaniMain}
{input one}
{snippet two}
{var $_form = $form = $presenter['hledaniMain']}
{input hledaniMain-two}
{/snippet}
{snippet three}
{var $_form = $form = $presenter['hledaniMain']}
{input hledaniMain-three}
{/snippet}
{input send}
{/form}
?>
v javascriptu:
<script>
$(function(){
$.nette.init();
$('body').on('change', 'select[name=one]', function () {
$.nette.ajax({
url: '?do=hledaniMain-invalidateTwo',
data: {
'hledaniMain-value': $('select[name=one]').val(),
}
});
});
$('body').on('change', 'select[name=two]', function () {
$.nette.ajax({
url: '?do=**hledaniMain-invalidateThree',
data: {
'hledaniMain-valueOne': $('select[name=one]').val(),
'hledaniMain-valueTwo': $('select[name=two]').val(),
}
});
});
});
</script>
Pro úplnost funkčního řešení Komponenty obsahující formulář
s ajaxem pomocí snipettu:
V komponentě:
<?php
namespace App\FrontModule\forms;
use \Nette\Application\UI,
Nette\ComponentModel\IContainer,
Nette\Forms;
use Nette\Application\UI\form;
use Nette\Diagnostics\Debugger;
class HledaniMain extends \Nette\Application\UI\Control
{
private $databaseOne = ['1', '2', '3'];
private $databaseTwo = [
['11', '12', '13'],
['22', '23', '24'],
['33', '34', '35'],
];
private $databaseThree = [
[
['111', '112', '113'],
['121', '122', '123'],
['131', '132', '133'],
],
[
['222', '223', '224'],
['232', '233', '234'],
['242', '243', '244'],
],
[
['333', '334', '335'],
['343', '344', '345'],
['353', '354', '355'],
],
];
public function render()
{
$template = $this->createTemplate();
$template->setFile(__DIR__ . '/templates/hledaniMain.latte');
$template->registerFilter(new \Nette\Latte\Engine());
$template->render();
}
protected function createComponentHledaniMain($name){
$this->form = new \Nette\Application\UI\Form;
$this->template->__form = $this->form;
$this->form->addSelect('one', 'One', $this->databaseOne)->setDefaultValue(1);
$this->form->addSelect('two', 'Two', $this->databaseTwo[$this->form['one']->value])->setDefaultValue(1);
$this->form->addSelect('three', 'Three', $this->databaseThree[$this->form['two']->value][1])->setDefaultValue(1);
$this->form->addSubmit('send', 'Odeslat');
$this->form->onSuccess[] = $this->success;
return $this->form;
}
public function getForm(){
return $this->form;
}
public function success(UI\Form $form, $vals) {
dump($vals);
}
public function handleInvalidateTwo($value) {
//$this->createComponentHledaniMain("hledaniMain");
$this['hledaniMain']['two']->setItems($this->databaseTwo[$value]);
$this['hledaniMain']['three']->setItems($this->databaseThree[$value][0]);
$this->redrawControl();
}
public function handleInvalidateThree($valueOne, $valueTwo) {
$this['hledaniMain']['three']->setItems($this->databaseThree[$valueOne][$valueTwo]);
$this->redrawControl('three');
}
}
?>
a nakonec v presenteru:
<?php
class HomepagePresenter extends BasePresenter
{
public function renderDefault()
{
}
protected function createComponentHledaniMain($name)
{
$form = new \App\FrontModule\Forms\HledaniMain($this,$name);
return $form;
}
?>
a kdyby náhodou tak ještě v šabloně presenteru se zavolá formulář takhle:
<?php
{control hledaniMain}
?>