AJAX, jQuery a správnéh použití snippetů
- hiny
- Člen | 35
Zdravím, potýkám se tu už pár dní s několika problémemy okolo AJAXu, jQuery a správného použití snippetů a možná nette všeobecně.
Už jsem tak dokonale zmaten, z neustáleho přepisování a upravování kódu, dle různých témat co jsem zde na fóru našel, že už vlastně pořádně nevím co dělám. Takže možná raději popíšu čeho se snažím docílit a pak sem vložím nějakej ten kód.
Tvořím komponentu pro kalkulaci, jde vlastně o formulář se 6 selectboxy, kde při výběru 1. selectboxu se načte obsah druhého, třetího,… až volbou 6. selectu se formulář odešle. To vše pomocí ajaxu.
Ještě do nedávna mi vše fungovalo, ale to jsem měl vše „napráskané“ v default presenteru a nepoužíval jsem snippety. Ale nyní jsem se to rozhodl dát bokem do komponenty a využít snippety, ale dokonale jsem se do toho zamotal.
Takže teď ten kód ve zkráceném znění:
root\_app\templates\@layout.phtml
@{include $content}
root\_app\templates\Default.default.phtml
@{control kalkulace}
root\_app\components\KalkulaceControl.php
<?php
class KalkulaceControl extends Control
{
public $barevnost = array( '0' => 'zvolte možnost', '10' => '1/0', '40' => '4/0' );
public $pocet = array( '0' => 'zvolte možnost','1000' => '1.000', '2000' => '2.000',);
public $default_selectbox = array( '0' => 'zvolte možnost' );
protected function createComponentKalkulaceForm($name)
{
$form = new AppForm($this, $name);
$form->addSelect('barevnost', NULL, $this->barevnost)
->skipFirst()
->addRule(Form::FILLED)
->getControlPrototype()->onchange('loadBox(1, this.value);');
$form->addSelect('pocet', NULL, $this->default_selectbox)
->skipFirst()
->addRule(Form::FILLED)
->getControlPrototype()->onchange('loadBox(2, this.value);');
$form->addImage('spocitat', $this->template->baseUri . 'img/sipka.png', 'Spočítat')
->onClick[] = array($this, 'submitForm');
// zde jsou nějaké podmínky s promazanou částí kódu
// jde v podstatě pouze o podporu funkčnosti bez JS
return $form;
}
public function submitForm(ImageButton $button)
{
}
public function handleLoadData($phase, $value)
{
$form = $this->getComponent('kalkulaceForm');
if ($phase == 1) {
$form['pocet']->setItems( $this->pocet )->setDisabled(false);
//echo $form['pocet']->getControl();
}
//$this->terminate();
}
public function render()
{
$template = $this->getTemplate();
$template->setFile(dirname(__FILE__) . '/kalkulace_form.phtml');
$template->kalkulace = $this->getComponent('kalkulaceForm');
$template->render();
}
}
?>
root\_app\components\kalkulace_form.phtml
<!-- red-line zacatek -->
{!$kalkulace->render('begin')}
<div id="red-line">
<div id="sipka">
{!$kalkulace['spocitat']->control}
</div>
<!-- kalkulace zacatek -->
<div id="kalkulace">
<div class="kalkulace_typ" id="barevnost">
{snippet barevnost}
{!$kalkulace['barevnost']->control}
{/snippet}
</div>
<div class="kalkulace_typ" id="pocet">
{snippet pocet}
{!$kalkulace['pocet']->control}
{/snippet}
</div>
</div>
<!-- kalkulace konec -->
</div>
{!$kalkulace->render('end')}
<!-- red-line konec -->
root\js\kalkulace.js
<script>
function disableSelects()
{
$('#frmkalkulaceForm-pocet').attr('disabled', true);
$('#frmkalkulaceForm-pocet').val(0);
$('#frmkalkulaceForm-spocitat').attr('disabled', true);
}
function loadBox(phase, value)
{
if (phase === 1) {
spinner();
// natáhne obsah dalšího selectboxu pomocí AJAXu
$.get("?do=kalkulace-loadData", {"phase": phase, "value": value}, function (payload) {
$.nette.success(payload);
});
}
else if (phase === 2) {
// zde nasleduje odeslání formuláře
}
}
</script>
Do stránky je dále načten soubor s AJAX Nette Framwork plugin for jQuery v. 0.2
Po zvolení barevnosti, se mi ve firebugu zobrazi toto:
{"state":[],"snippets":{"kalkulace__barevnost":"\t\t\t\t<select onfocus=\"this.onmousewheel=function(){return false}\" onchange=\"loadBox(1, this.value);\" name=\"barevnost\" id=\"frmkalkulaceForm-barevnost\"><option value=\"0\">zvolte mo\u017enost<\/option><\/select>\r\n","kalkulace__pocet":"\t\t\t\t<select onfocus=\"this.onmousewheel=function(){return false}\" onchange=\"loadBox(2, this.value);\" name=\"pocet\" id=\"frmkalkulaceForm-pocet\"><option value=\"0\">zvolte mo\u017enost<\/option><\/select>\r\n"}}
Což je ale, výchozí stav formuláře. Jen se navíc povolí všechny selecty, které při načtení stránky zakazuji JS a poté postupně povoluji.
Najde se nějaká ochotná duše, která pochopila o co se snažím a která mi s tím poradí, popř. alespoň pomyslně nakopne správným směrem?
Editoval hiny (29. 10. 2009 12:14)
- Tomik
- Nette Evangelist | 485
Abych se přiznal debugovat celý tento kód by pro mě bylo v tuto hodinu
velmi náročné, ale nikde tam nevidím
$this->invalidateControl();
, resp.
$this->invalidateControl('barevnost');
, tudíž nemůže dojít
k poslání tohoto snippetu, i když je potřeba. Moje rada tedy zní: zkusit
bych do handleLoadData
dát odpovídající invalidování
snippetů…
- hiny
- Člen | 35
Tak jsem to tam zkusil (znovu) dát, ale bohužel bez výsledku. Neudělá to žádnou změnu, vše se tváří stejně.
<?php
public function handleLoadData($phase, $value)
{
$form = $this->getComponent('kalkulaceForm');
if ($phase == 1) {
$form['pocet']->setItems( $this->pocet )->setDisabled(false);
//echo $form['pocet']->getControl();
$this->invalidateControl('pocet');
// nefunguje ani nasledující
//$this->invalidateControl();
}
//$this->terminate();
}
?>
- hiny
- Člen | 35
Tak jsem na základě tvé otázky, právě zjistil, že se mi to do té podmínky nedostane a nějak to vůbec nechápu.
public function handleLoadData($phase, $value)
{
$form = $this->getComponent('kalkulaceForm');
if ($phase == 1) {
$form['pocet']->setItems( $this->pocet )->setDisabled(false);
//$this->invalidateControl('pocet');
}
// tohle funguje, ale to je asi tak vše
// echo "test";
$this->invalidateControl();
}
- hiny
- Člen | 35
vlki napsal(a):
Protože to předáš jako nějaké obecné parametry. Pokud mají patřit komponentě, musí být prefixovaný názvem komponenty. Zkus něco jako…
<script> ... $.get("?do=kalkulace-loadData", {"kalkulace-phase": phase, "kalkulace-value": value}, function (payload) { ... </script>
Super, díky. Tohle pomohlo a už to dělá co má :-)