závislý selectbox – chyba při překreslení snippetu
- admin@easyweb4u.cz
- Backer | 146
Vytvořil jsem závislý selectbox.
Šablona
<?php
<form class="ajax" n:name="terapeutsForm">
<input n:name="calendarid">
<table>
<tr>
<td>
Terapeut:
</td>
<td>
<select id="static" n:name="terapeutid"></select>
</td>
</tr>
<tr>
<td>
Cena:
</td>
<td>
{snippet price}
<select n:name="price"></select>
{/snippet}
</td>
</tr>
<tr>
<td>
</td>
<td>
<input n:name="send">
</td>
</table>
</form>
?>
script
<script type="text/javascript">
$('#static').change(function() {
$.get("?do=selectLoad", {"terapeutid": $(this).val()});
});
</script>
handler
<?php
public function handleSelectLoad($terapeutid)
{
$form = $this->getComponent('terapeutsForm'); // our form
$newPrice = [];
$select = $this->database->table('priceter')->where('terapeutid = ?', $terapeutid)->fetchAll();
if ($select != null) {
foreach ($select as $s) {
$newPrice[$s->price] = $s->nameservice . ' ' . $s->price;
}
}
$form['price']->setItems($newPrice); // set up new values
$this->redrawControl('price'); // invalidate ajax snippet
}
?>
a formulář
<?php
namespace App\Forms;
use Nette;
use Nette\Application\UI;
class TerapeutsFormFactory
{
/** @var Nette\Database\Context */
private $database;
public function __construct(Nette\Database\Context $database) {
$this->database = $database;
}
public function create($calendarid)
{
$form = new UI\Form;
$form->addProtection();
$form->addHidden('calendarid', $calendarid);
$select = $this->database->table('terapeut')->order('surname')->fetchAll();
$data = [];
if ($select != null) {
$i = 0;
foreach ($select as $s) {
$data[$s->id] = $s->surname . ' ' . $s->name;
if ($i === 0) {
$sel = $this->database->table('priceter')->where('terapeutid = ?', $s->id)->fetchAll();
if ($sel != null) {
foreach ($sel as $e) {
$price[$e->price] = $e->nameservice . ' ' . $e->price;
}
}
}
$i++;
}
}
$form->addSelect('terapeutid', 'Terapeut:', $data);
$form->addSelect('price', 'Cena:', $price);
$form->addSubmit('send', 'Přidat terapeuta')
->setAttribute('class', 'btn btn-success');
//$form->getElementPrototype()->class('ajax');
$form->onSuccess[] = [$this, 'processTerapeutsForm'];
return $form;
}
public function processTerapeutsForm($form, $values)
{
$insert = $this->database->query('INSERT INTO semiterapeut', [
'calendarid' => $values->calendarid,
'terapeutid' => $values->terapeutid,
'price' => $values->price
]);
}
}
?>
Ono to funguje částečně. Při výběru option se objeví chyba
end() expects parameter 1 to be array, null given
330: $this->global->snippetDriver->leave();
331:
332: }
333:
334:
335: function blockPrice($_args)
336: {
337: extract($_args);
338: $this->global->snippetDriver->enter(„price“,
„static“);
339: ?> <select<?php
340: $_input = end($this->global->formsStack)[„price“];
341: echo $_input->getControlPart()->attributes() ?>><?php echo
$_input->getControl()->getHtml() ?></select>
342: <?php
343: $this->global->snippetDriver->leave();
ale po kliknutí na skip error se závislý select překreslí správnými hodnotami (ale statický select zůstane na 1. – defaultní – hodnotě). Zkusil jsem kolem formuláře dát snippetArea, pak to chybu nehlásí, ale závislý select se nepřepíše.
- admin@easyweb4u.cz
- Backer | 146
MajklNajt napsal(a):
ahoj, aby ti fungoval snippet vo formulári, musíš formulár obaliť do snippetArea, len potom musíš v handleSelectLoad invalidovať aj tú snippetAreu
No to jsem zkusil, chybu to nehlásilo, ale nepřekreslil se ten vnitřní snippet.
Editoval admin@easyweb4u.cz (20. 11. 2018 20:26)
- admin@easyweb4u.cz
- Backer | 146
MajklNajt napsal(a):
Aha, už vidím, v tom JS callbacku by si mal použiť $.nette.ajax() namiesto $.get(), preto sa to snippet neprekreslí
Chyba: Column operator does not accept null argument.
Z toho statického selectu se nyní nepřenesl parameter terapeutid (357: $select = $this->database->table(‚priceter‘)->where(‚terapeutid = ?‘, $terapeutid)->fetchAll();)
- admin@easyweb4u.cz
- Backer | 146
MajklNajt napsal(a):
resp. úplne správne takto:
<script> $.nette.ajax({ type: "GET", url: "?do=selectLoad", data: {"terapeutid": $(this).val()} }); </script>
Díky moc, funguje to :-)
- MajklNajt
- Člen | 498
CZechBoY napsal(a):
@MajklNajt A jeste lip tak abys vse generoval v Nette a ne rucne…
Nemas nahodou ten formular v komponente?
áno, dá sa to aj krajšie, len cez mobil sa mi to nechcelo vypisovať :D ja to mám napr. v takejto konštrukcií:
{include callbackJs, link => "selectLoad", form => "terapeutsForm", input => "terapeutid"}
{define callbackJs}
<script>
$("#" + {$control[$form][$input]->htmlId}).off("change").on("change", function () {
$.nette.ajax({
type: "GET",
url: {link {$link}!},
data: {
{$input}: $(this).val(),
}
});
});
</script>
{/define}
- admin@easyweb4u.cz
- Backer | 146
CZechBoY napsal(a):
@MajklNajt A jeste lip tak abys vse generoval v Nette a ne rucne…
Nemas nahodou ten formular v komponente?
No mam. Teď závislý select funguje, ale odesílá se (a uloží) pouze první hodnota (včetně té závislé).
Editoval admin@easyweb4u.cz (21. 11. 2018 9:08)
- admin@easyweb4u.cz
- Backer | 146
admin@easyweb4u.cz napsal(a):
MajklNajt napsal(a):
resp. úplne správne takto:
<script> $.nette.ajax({ type: "GET", url: "?do=selectLoad", data: {"terapeutid": $(this).val()} }); </script>
Díky moc, funguje to :-)
Teď závislý select funguje, ale odesílá se (a uloží) pouze první hodnota (včetně té závislé).
Editoval admin@easyweb4u.cz (21. 11. 2018 9:09)
- admin@easyweb4u.cz
- Backer | 146
MajklNajt napsal(a):
@admin@easyweb4u.cz čo máš na mysli pod prvou hodnotou? prvý select alebo prvá value z oboch selectov?
mimochodom, ten kto mi dal mínusku, by mohol aj napísať, čo zlé som poradil, nech sa aj ja poučím…
já jí tam nedal … :-)
No funguje to tak, že když proklikávám první select, správně se mi objevují hodnoty v závislém selectu. Ale hodnoty se odešlou pouze v případě nastavení na první hodnotu prvního selectu (včetně správné zvolené hodnoty závislého selectu). Když se podívám do zdrojového kódu překresleného formuláře, vidím v závislém selectu pouze hodnoty pro první select, i když v prohlížeči vidím vše správně překreslené. Už jsem z toho na palici.
Poznámka: už jsem to tu psal, formulář mám v komponentě.
ještě jsem taky neuvedl tenhle kód v prezenteru
<?php
protected function createComponentTerapeutsForm()
{
$form = $this->terapeutsFormFactory->create($this->id);
$form->onSuccess[] = function (Form $form) {
if (!$this->isAjax()) {
$this->flashMessage('Error');
} else {
$this->flashMessage('Přidání terapeuta proběhlo úspěšně.');
$this->redrawControl('terapeuts');
$this->redrawControl('flashesAdmin');
}
};
return $form;
}
?>
Editoval admin@easyweb4u.cz (21. 11. 2018 10:49)
- CZechBoY
- Člen | 3608
@MajklNajt Je špatně to, že kompletně odebíráš ostatní
onchange handlery na inputu. Dále je potřeba počítat s tím, že form
může být v komponentě a je teda potřeba parametr pojmenovat správně
i s cestou ke komponentě.
Takže správně by to mělo být snad takto:
{include callbackJs, link => "selectLoad", form => "terapeutsForm", input => "terapeutid"}
{define callbackJs}
<script>
$("#" + {$control[$form][$input]->htmlId}).on("change", function () {
$.nette.ajax({
type: "GET",
url: {link {$link}!},
data: {
{$control[$form]->getParameterId($input)}: $(this).val(),
}
});
});
</script>
{/define}
- admin@easyweb4u.cz
- Backer | 146
CZechBoY napsal(a):
@MajklNajt Je špatně to, že kompletně odebíráš ostatní onchange handlery na inputu. Dále je potřeba počítat s tím, že form
může být v komponentě a je teda potřeba parametr pojmenovat správně i s cestou ke komponentě.Takže správně by to mělo být snad takto:
{include callbackJs, link => "selectLoad", form => "terapeutsForm", input => "terapeutid"} {define callbackJs} <script> $("#" + {$control[$form][$input]->htmlId}).on("change", function () { $.nette.ajax({ type: "GET", url: {link {$link}!}, data: { {$control[$form]->getParameterId($input)}: $(this).val(), } }); }); </script> {/define}
Hlásí to chybu: Call to undefined method Nette\Application\UI\Form::getParameterId().
- MajklNajt
- Člen | 498
@admin@easyweb4u.cz skús z toho urobiť komponentu týmto spôsobom: https://doc.nette.org/…s/form-reuse#…, kde potom ten handler budeš mať v tej komponente (nie v presenteri, ako to zrejme máš teraz)
@CZechBoY ja som len napísal, ako to používam ja, nie, že je to superuniverzálne a jediné správne riešenie, no zatiaľ som si s tým takto vystačil (aby som dodržal DRY prístup)… samozrejeme, vždy je čo zlepšovať, ďakujem za vysvetlenie :) prekvapilo ma iba mínus bez akéhokoľvek komentára (osobne dávam mínus iba na príspevok, ktorý je úplne off topic alebo je zjavne nesprávny)
- CZechBoY
- Člen | 3608
@MajklNajt on je nesprávný v těch bodech co jsme psal… nenapsal
jsem dřív protože se mi to nechtělo psát na mobilu :D
Nakonec ani ten můj kod není správný…
{include callbackJs, link => "selectLoad", form => "terapeutsForm", input => "terapeutid"}
{define callbackJs}
<script>
$("#" + {$control[$form][$input]->htmlId}).on("change", function () {
$.nette.ajax({
type: "GET",
url: {link {$link}!},
data: {
{$control[$form][$input]->lookupPath()}: $(this).val(),
}
});
});
</script>
{/define}
- admin@easyweb4u.cz
- Backer | 146
CZechBoY napsal(a):
@MajklNajt on je nesprávný v těch bodech co jsme psal… nenapsal jsem dřív protože se mi to nechtělo psát na mobilu :D
Nakonec ani ten můj kod není správný…{include callbackJs, link => "selectLoad", form => "terapeutsForm", input => "terapeutid"} {define callbackJs} <script> $("#" + {$control[$form][$input]->htmlId}).on("change", function () { $.nette.ajax({ type: "GET", url: {link {$link}!}, data: { {$control[$form][$input]->lookupPath()}: $(this).val(), } }); }); </script> {/define}
Tak teď se po události change odesílají tyhle parametry:
Therapy:default
id = 31
do = selectLoad
terapeutsForm-terapeutid = 5
Ale handler hodí chybu
Column operator does not accept null argument.
Což značí, že se do něj nepřenese parametr terapeutid resp. terapeutsForm-terapeutid)
- admin@easyweb4u.cz
- Backer | 146
Tak stále na mrtvém bodě. Já jsem nyní vyjmul ten formulář z komponenty a strčil ho do presenteru. Ale nijak jsem si nepomohl. Chová se to úplně stejně.
Pro změnu závislého selektu používám toto – funguje to:
<script type="text/javascript">
$('#static').change(function() {
$.nette.ajax({
type: "GET",
url: {link selectLoad!},
data: {"terapeutid": $(this).val()}
});
});
</script>
Ale, data a následné uložení odeslaných parametrů se provedou pouze pro první položku statického selectu, a to i když před tím proklikám oba selecty. Pokud nastavím jinou než první položku, ajax se sice provede – volá se správný presenter a id
Therapy:default
id = 31
ale dle mého pozorování se vůbec nevolá funkce, která formulář zpracovává (je též v presenteru).
<?php
public function processTerapeutsForm($form, $values)
{
if (!$this->isAjax()) {
$this->flashMessage('Error');
} else {
$this->flashMessage('TID:' . $values->terapeutid);
$insert = $this->database->query('INSERT INTO semiterapeut', [
'calendarid' => $this->id,
'terapeutid' => $values->terapeutid,
'price' => $values->price
]);
if ($insert) {
$this->flashMessage('Přidání terapeuta proběhlo úspěšně.');
$this->redrawControl('terapeuts');
} else {
$this->flashMessage('Chyba! Přenos dat se nezdařil.');
}
}
$this->redrawControl('flashesAdmin');
}
?>
Pokud závislý select vyřadím, vše funguje jak má.
Věděl by někdo?
- admin@easyweb4u.cz
- Backer | 146
admin@easyweb4u.cz napsal(a):
Tak stále na mrtvém bodě. Já jsem nyní vyjmul ten formulář z komponenty a strčil ho do presenteru. Ale nijak jsem si nepomohl. Chová se to úplně stejně.
Pro změnu závislého selektu používám toto – funguje to:
<script type="text/javascript"> $('#static').change(function() { $.nette.ajax({ type: "GET", url: {link selectLoad!}, data: {"terapeutid": $(this).val()} }); }); </script>
Ale, data a následné uložení odeslaných parametrů se provedou pouze pro první položku statického selectu, a to i když před tím proklikám oba selecty. Pokud nastavím jinou než první položku, ajax se sice provede – volá se správný presenter a id
Therapy:default
id = 31ale dle mého pozorování se vůbec nevolá funkce, která formulář zpracovává (je též v presenteru).
<?php public function processTerapeutsForm($form, $values) { if (!$this->isAjax()) { $this->flashMessage('Error'); } else { $this->flashMessage('TID:' . $values->terapeutid); $insert = $this->database->query('INSERT INTO semiterapeut', [ 'calendarid' => $this->id, 'terapeutid' => $values->terapeutid, 'price' => $values->price ]); if ($insert) { $this->flashMessage('Přidání terapeuta proběhlo úspěšně.'); $this->redrawControl('terapeuts'); } else { $this->flashMessage('Chyba! Přenos dat se nezdařil.'); } } $this->redrawControl('flashesAdmin'); } ?>
Pokud závislý select vyřadím, vše funguje jak má.
Věděl by někdo?
Kluci, už to neřešte, chyba u mně, natvrdo jsem si k první položce přiřadil závislé položky, měl jsem použít setDefaults()…