Dependent form select with AJAX
- majo1
- Člen | 103
Ahojte,
mám formulár, kde sa snažím spraviť 3 select boxy, závislé od hodnoty
toho prvého.
Rozhodol som sa, že pôjdem podľa postupu https://blog.nette.org/…-and-pure-js
V layoute síce vykreslí labels a select boxy – first select, second select, third select a submit button, no po výbere hodnoty vo first select sa nenačítajú hodnoty do ostatných select boxov.
Viete mi prosím poradiť, s čím môže byť problém?
Ďakujem
presenter
<?php
namespace App\Presenters;
use Nette\Application\UI\Form;
class HomepagePresenter extends BasePresenter
{
public function renderDefault()
{
$this->template->_form = $this['selectForm'];
}
/**
* Load values to second select
* @param int
*/
public function handleFirstChange($value)
{
if ($value) {
$secondItems = array(
1 => 'First option ' . $value . ' - second option 1',
2 => 'First option ' . $value . ' - second option 2'
);
$this['selectForm']['second']->setPrompt('Select')
->setItems($secondItems);
$this['selectForm']['third']->setPrompt('Select from second');
} else {
$this['selectForm']['second']->setPrompt('Select from first')
->setItems(array());
$this['selectForm']['third']->setPrompt('Select from first')
->setItems(array());
}
$this->invalidateControl('secondSnippet');
}
/**
* Load values to third select
* @param int
*/
public function handleSecondChange($value)
{
if ($value) {
$thirdItems = array(
1 => 'Second option ' . $value . ' - third option 1',
2 => 'Second option ' . $value . ' - third option 2'
);
$this['selectForm']['third']->setPrompt('Select')
->setItems($thirdItems);
} else {
$this['selectForm']['third']->setPrompt('Select from second')
->setItems(array());
}
$this->invalidateControl('thirdSnippet');
}
/********************** form **********************/
protected function createComponentSelectForm()
{
$firstItems = array(
1 => 'First option 1',
2 => 'First option 2'
);
$form = new Form;
$form->addSelect('first', 'First select:', $firstItems)
->setPrompt('Select');
$form->addSelect('second', 'Second select:')
->setPrompt('Select from first');
$form->addSelect('third', 'Third select:')
->setPrompt('Select from first');
$form->addSubmit('send', 'Submit');
$form->onSuccess[] = $this->processSelectForm;
return $form;
}
/**
* @param form
*/
public function processSelectForm(Form $form)
{
// same as above
}
}
latte
{define #content}
{form selectForm}
{label first /} {input first}
{snippet secondSnippet}
{label second /} {input second}
{snippet thirdSnippet}
{label third /} {input third}
{/snippet}
{include #js}
{/snippet}
{input send}
{/form}
{/define}
{define #js}
<script type="text/javascript">
{include #jsCallback, input => first, link => firstChange}
{include #jsCallback, input => second, link => secondChange}
</script>
{/define}
{define #jsCallback}
{* same as above *}
{/define}
na konci @layout.latte pouzivam
<script src="{$basePath}/dist/js/nette.ajax.js"></script>
<script>
$(function () {
$.nette.init();
});
</script>
- majo1
- Člen | 103
je to asi taka primitivna chyba, ale ucim sa :)
snazil som sa do premennej $ziskaneIdCentra zapisat id strediska, ktore je ako
value v 1. Select boxe.
Na zaklade tohoto ID chcem vyfiltrovat:
- termin skibusu (druhy selectbox), IDE
- zastavku (treti selectbox), NEJDE, pise len „najskor vyberte skibus“
viete prosim poradit?
dakujem
<?php
namespace App\Presenters;
use App\Model\ReservationformManager;
use Nette\Application\UI\Form;
class HomepagePresenter extends BasePresenter
{
private static $ziskaneIdCentra;
protected $reservationformManager;
public function __construct(ReservationformManager $reservationformManager)
{
parent::__construct();
$this->reservationformManager = $reservationformManager;
}
public function renderDefault()
{
// required to enable form access in snippets
$this->template->_form = $this['selectForm'];
}
/**
* Load values to second select
* @param int
*/
public function handleFirstChange($value)
{
if ($value) {
self::$ziskaneIdCentra = $value;
$resultSk = $this->reservationformManager->getSkibusSel(self::$ziskaneIdCentra);
$secondItems = $resultSk->fetchPairs('idskibus', 'departureDatetime');
$this['selectForm']['second']->setPrompt('-- vyberte --')
->setItems($secondItems);
$this['selectForm']['third']->setPrompt('-- najskôr vyberte skibus --');
} else {
$this['selectForm']['second']->setPrompt('-- vyberte najskôr stredisko --')
->setItems(array());
$this['selectForm']['third']->setPrompt('-- vyberte najskôr stredisko --')
->setItems(array());
}
$this->invalidateControl('secondSnippet');
}
public function handleSecondChange($value)
{
if ($value) {
$resultSt = $this->reservationformManager->getStationSel(self::$ziskaneIdCentra); //$ziskaneIdCentra
$thirdItems = $resultSt->fetchPairs('idstation', 'city'); //city spojit s casom
$this['selectForm']['third']->setPrompt('-- vyberte --')
->setItems($thirdItems);
} else {
$this['selectForm']['third']->setPrompt('-- najskôr vyberte skibus --')
->setItems(array());
}
$this->invalidateControl('thirdSnippet');
}
/********************** form **********************/
protected function createComponentSelectForm()
{
$resultCe = $this->reservationformManager->getCenter();
$firstItems = $resultCe->fetchPairs('idcenter', 'centerName');
$form = new Form;
$form->addSelect('first', 'Stredisko: ', $firstItems)
->setPrompt('-- vyberte --');
$form->addSelect('second', 'Skibus - termín: ')
->setPrompt('-- vyberte najskôr stredisko--');
$form->addSelect('third', 'Zastávka: ')
->setPrompt('-- vyberte najskôr stredisko--');
$form->addSubmit('send', 'Submit');
$form->onSuccess[] = $this->processSelectForm;
return $form;
}
/**
* @param form
*/
public function processSelectForm(Form $form)
{
// $form->getValues() ignores invalidated input's values
$values = $form->getHttpData();
unset($values['send']);
dump($values);
}
}
- F.Vesely
- Člen | 369
private static $ziskaneIdCentra;
Tohle vyhod, na tohle se staticke promenne nepouzivaji.
Proc potrebujes nejdrive vybrat skibus, nez dovolis vybrat zastavku? Nestaci ti jenom:
/**
* Load values to second select
* @param int
*/
public function handleFirstChange($value)
{
if ($value) {
$resultSk = $this->reservationformManager->getSkibusSel($value);
$secondItems = $resultSk->fetchPairs('idskibus', 'departureDatetime');
$this['selectForm']['second']->setPrompt('-- vyberte --')
->setItems($secondItems);
$resultSt = $this->reservationformManager->getStationSel($value); //$ziskaneIdCentra
$thirdItems = $resultSt->fetchPairs('idstation', 'city'); //city spojit s casom
$this['selectForm']['third']->setPrompt('-- vyberte --')
->setItems($thirdItems);
} else {
$this['selectForm']['second']->setPrompt('-- vyberte najskôr stredisko --')
->setItems(array());
$this['selectForm']['third']->setPrompt('-- vyberte najskôr stredisko --')
->setItems(array());
}
$this->invalidateControl('secondSnippet');
}
- majo1
- Člen | 103
ďakujem za radu, takto to je ideálne :)
už ma len jedna vec trápi,
ako tie selecty kvôli snippetom manuálne vyrenderovať do tohoto formátu
<div class="form-group">
<label n:name=second>Skibus*</label>
<select n:name=second class="form-control">
<option></option>
</select>
</div>
a do tohoto latte nehcem ťahať hlavné @layout.latte
Editoval majo1 (5. 2. 2016 15:56)
- majo1
- Člen | 103
chcem totiž, selectboxy doplniť do tohoto latte
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="{$basePath}/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
<link rel="stylesheet" href="{$basePath}/dist/css/AdminLTE.min.css">
<link rel="stylesheet" href="{$basePath}/dist/css/skins/skin-blue.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<style>
.alert-dismissable .close, .alert-dismissible .close { right: 0; }
</style>
<div n:foreach="$flashes as $flash" style="padding: 15px;">
<div class="box-body alert alert-info alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-info"></i> {$flash->message}</h4>
</div>
</div>
<form n:name=reservationForm class=form>
<div n:if="$form->hasErrors()" class="callout callout-warning">
<h4>Chyba!</h4>
<p n:foreach="$form->errors as $error">{$error}</p>
</div>
<div class="form-group">
<label n:name=resdetail-center_idcenter>Stredisko*</label>
<select n:name=resdetail-center_idcenter class="form-control">
<option></option>
</select>
</div>
<div class="form-group">
<label n:name=resdetail-skibus_idskibus>Skibus*</label>
<select n:name=resdetail-skibus_idskibus class="form-control">
<option></option>
</select>
</div>
<div class="form-group">
<label n:name=resdetail-station_idstation>Zastávka*</label>
<select n:name=resdetail-station_idstation class="form-control">
<option></option>
</select>
</div>
<div class="input-group">
<label n:name=resdetail-numAdult>Počet dospelých*
<div class="input-group">
<input type="number" min="0" max="100" class="form-control" n:name=resdetail-numAdult>
<div class="input-group-addon">
<i class="fa fa-child"></i>
</div>
</div>
</label>
</div>
<div class="input-group">
<label n:name=resdetail-numJunior>Počet juniorov*
<div class="input-group">
<input type="number" min="0" max="100" class="form-control" n:name=resdetail-numJunior>
<div class="input-group-addon">
<i class="fa fa-child"></i>
</div>
</div>
</label>
</div>
<div class="input-group">
<label n:name=resdetail-numKid>Počet detí*
<div class="input-group">
<input type="number" min="0" max="100" class="form-control" n:name=resdetail-numKid>
<div class="input-group-addon">
<i class="fa fa-child"></i>
</div>
</div>
</label>
</div>
<div class="input-group">
<label n:name=resdetail-numTransportOnly>Len doprava*
<div class="input-group">
<input type="number" min="0" max="100" class="form-control" n:name=resdetail-numTransportOnly>
<div class="input-group-addon">
<i class="fa fa-bus"></i>
</div>
</div>
</label>
</div>
<div class="input-group">
<label n:name=custdetail-name>Meno*
<div class="input-group">
<input class="form-control" n:name=custdetail-name>
<div class="input-group-addon">
<i class="fa fa-user"></i>
</div>
</div>
</label>
</div>
<div class="input-group">
<label n:name=custdetail-surename>Priezvisko*
<div class="input-group">
<input class="form-control" n:name=custdetail-surename>
<div class="input-group-addon">
<i class="fa fa-user"></i>
</div>
</div>
</label>
</div>
<div class="input-group">
<label n:name=custdetail-telephone>Telefón*
<div class="input-group">
<input class="form-control" n:name=custdetail-telephone>
<div class="input-group-addon">
<i class="fa fa-phone"></i>
</div>
</div>
</label>
</div>
<div class="input-group">
<label n:name=custdetail-email>E-mail
<div class="input-group">
<input class="form-control" n:name=custdetail-email>
<div class="input-group-addon">
<i class="fa fa-envelope"></i>
</div>
</div>
</label>
</div>
<p><input n:name=submit class="btn btn-primary"></p>
</form>
<script src="http://momentjs.com/downloads/moment.min.js"></script>
<script src="{$basePath}/plugins/jQuery/jQuery-2.1.4.min.js"></script>{include #js}
<script src="{$basePath}/bootstrap/js/bootstrap.min.js"></script>
<script src="{$basePath}/dist/js/app.min.js"></script>
<script src="{$basePath}/dist/js/demo.js"></script>
<link rel="stylesheet" href="{$basePath}/plugins/timepicker/bootstrap-timepicker.min.css">
<script src="{$basePath}/plugins/timepicker/bootstrap-timepicker.min.js"></script>
<link href="//cdn.rawgit.com/Eonasdan/bootstrap-datetimepicker/e8bddc60e73c1ec2475f827be36e1957af72e2ea/build/css/bootstrap-datetimepicker.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment-with-locales.js"></script>
<script src="//cdn.rawgit.com/Eonasdan/bootstrap-datetimepicker/e8bddc60e73c1ec2475f827be36e1957af72e2ea/src/js/bootstrap-datetimepicker.js"></script>
<script type="text/javascript">
$(function () {
$('#datetimepicker2').datetimepicker({
locale: 'sk',
useCurrent: true,
format: 'YYYY-MM-DD HH:mm'
});
});
</script>
<script>
$(function () {
//Timepicker
$(".timepicker").timepicker({
showInputs: false,
showMeridian: false,
minuteStep: 1,
defaultTime: 'current',
format: 'HH:mm'
});
});
</script>
</body>
</html>
Ďakujem
- majo1
- Člen | 103
- Funguje to. Ale chcel som sa vyhnut tomu, aby sa default.latte vykreslovalo v @layout.latte , co teraz robi :)
- Dalej pri submite hadze tracy chybu:
Model – Notice – Trying to get property of non-object
public function saveReservationform($reservationform)
25: {
26: $this->database->beginTransaction();
27: **$idcust = $this->database->table("customers")->insert($reservationform->custdetail)->idcustomer;**
28: $reservationform->resdetail->customer_idcustomer = $idcust;
29: $this->database->table("reservations")->insert($reservationform->resdetail);
30: $this->database->commit();
31: }
asi bude niekde chyba v presenteri. tato funkcia sa vola po kliknuti tlacidla submit
public function editorFormSucceeded($form, $values)
{
try {
$values = $form->getHttpData();
$this->reservationformManager->saveReservationform($values);
$this->flashMessage('Rezervácia bola úspešne odoslaná. Ďakujeme.');
//$this->redirect(':Reservationform:', $values->idreservation);
} catch (UniqueConstraintViolationException $ex) {
$this->flashMessage('Rezervácia s týmto ID už existuje!');
}
}
Editoval majo1 (5. 2. 2016 20:27)
- majo1
- Člen | 103
no $values = $form->getHttpData(); som zakomentoval :-)
teraz pise SQLSTATE[23000]: Integrity constraint violation: 1048 Column
‚skibus_idskibus‘ cannot be null
sql:
INSERT INTO reservations
(numAdult
, numJunior
, numKid
,
numTransportOnly
, center_idcenter
,
skibus_idskibus
, station_idstation
,
customer_idcustomer
)
VALUES (‚1‘, ‚2‘, ‚1‘, ‚5‘, 1, NULL, NULL, 56)
cize je asi niekde problem pri naplnani center_idcenter a skibus_idskibus do $values.
- majo1
- Člen | 103
do tracy som si dal vydumpovat $values:
array (5)
resdetail ⇒ array (7)
center_idcenter ⇒ „1“
skibus_idskibus ⇒ „2“
station_idstation ⇒ „1“
numAdult ⇒ „2“
numJunior ⇒ „0“
numKid ⇒ „1“
numTransportOnly ⇒ „0“
custdetail ⇒ array (4)
name ⇒ „Jozko“ (5)
surename ⇒ „Mrkvicka“ (8)
telephone ⇒ „0905 555 555“ (12)
email ⇒ „jozko@mrkvicka.sk" (17)
_submit ⇒ "Rezervovať skibus“ (18)
_token_ ⇒ „wvrg5df3culV5SbRSw2yvHtc3m6md3o0OKKyo=“ (38)
do ⇒ „reservationForm-submit“ (22)
($values = $form->getHttpData(); som odkomentoval, takze sa teraz vykonava) a zda sa , ze vsetky stlpce su teraz vyplnene a tracy aj tak pise Trying to get property of non-object
chyba vypisuje k riadku $idcust = $this->database->table(„customers“)->insert($reservationform->custdetail)->idcustomer;
Editoval majo1 (6. 2. 2016 10:27)
- enumag
- Člen | 2118
@majo1 Snippety jsou na závislé selecty zbytečně složité, úplně stačí použít tenhle addon.
- majo1
- Člen | 103
zasielam moj vypis z cmd
`Microsoft Windows [Version 6.1.7601]
Copyright © 2009 Microsoft Corporation. Všetky práva vyhradené.
C:\Users\majo>cd c:\xampp\htdocs\nitransnetteproject
c:\xampp\htdocs\nitransnetteproject>composer require nasext/dependent-select-box
Using version ^2.1 for nasext/dependent-select-box
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
– nette/nette v2.3.5 requires nette/application 2.3.5 → no matching
package
found.
– nette/nette v2.3.4 requires nette/application 2.3.4 → no matching
package
found.
– nette/nette v2.3.3 requires nette/application 2.3.3 → no matching
package
found.
– nette/nette v2.3.2 requires nette/application 2.3.3 → no matching
package
found.
– nette/nette v2.3.1 requires nette/application 2.3.2 → no matching
package
found.
– nette/nette v2.3.0 requires nette/application 2.3.1 → no matching
package
found.
– nette/nette v2.2.9 requires nette/application 2.2.6 → no matching
package
found.
– nette/nette v2.2.8 requires latte/latte 2.2.5 → no matching package
found
.
– nette/nette v2.2.7 requires nette/application 2.2.4 → no matching
package
found.
– nette/nette v2.2.6 requires nette/application 2.2.3 → no matching
package
found.
– nette/nette v2.2.5 requires nette/application 2.2.3 → no matching
package
found.
– nette/nette v2.2.4 requires nette/application 2.2.3 → no matching
package
found.
– nette/nette v2.2.3 requires nette/application 2.2.2 → no matching
package
found.
– nette/nette v2.2.2 requires nette/application 2.2.1 → no matching
package
found.
– nette/nette v2.2.12 requires nette/application 2.2.9 → no matching
packag
e found.
– nette/nette v2.2.11 requires nette/application 2.2.8 → no matching
packag
e found.
– nette/nette v2.2.10 requires nette/application 2.2.7 → no matching
packag
e found.
– nette/nette v2.2.1 requires nette/application 2.2.0 → no matching
package
found.
– nette/nette v2.2.0 requires nette/application 2.2.0 → no matching
package
found.
– Installation request for nasext/dependent-select-box ^2.1 → satisfiable
b
y nasext/dependent-select-box[v2.1.0].
– Conclusion: remove nette/application v2.3.9
– Conclusion: don't install nette/application v2.3.9
– nasext/dependent-select-box v2.1.0 requires nette/nette @dev →
satisfiabl
e by nette/nette[v2.1.10, v2.1.11, v2.1.12, v2.1.9, v2.0.10, v2.0.11, v2.0.12,
v
2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.18, v2.0.2, v2.0.3, v2.0.4,
v2.
0.5, v2.0.6, v2.0.7, v2.0.8, v2.0.9, v2.1.0, v2.1.1, v2.1.2, v2.1.3, v2.1.4,
v2.
1.5, v2.1.6, v2.1.7, v2.1.8, v2.2.0, v2.2.1, v2.2.10, v2.2.11, v2.2.12,
v2.2.2,
v2.2.3, v2.2.4, v2.2.5, v2.2.6, v2.2.7, v2.2.8, v2.2.9, v2.3.0, v2.3.1,
v2.3.2,
v2.3.3, v2.3.4, v2.3.5, v2.3.6, v2.3.7, v2.3.8].
– nette/nette v2.3.6 requires nette/application 2.3.6 → satisfiable by
nett
e/application[v2.3.6].
– nette/nette v2.3.7 requires nette/application 2.3.7 → satisfiable by
nett
e/application[v2.3.7].
– nette/nette v2.3.8 requires nette/application 2.3.8 → satisfiable by
nett
e/application[v2.3.8].
– Can only install one of: nette/application[v2.3.6, v2.3.9].
– Can only install one of: nette/application[v2.3.7, v2.3.9].
– Can only install one of: nette/application[v2.3.8, v2.3.9].
– nette/nette v2.0.10 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.11 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.12 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.13 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.14 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.15 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.16 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.17 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.18 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.2 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.3 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.4 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.5 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.6 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.7 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.8 conflicts with nette/application[v2.3.9].
– nette/nette v2.0.9 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.0 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.1 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.10 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.11 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.12 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.2 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.3 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.4 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.5 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.6 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.7 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.8 conflicts with nette/application[v2.3.9].
– nette/nette v2.1.9 conflicts with nette/application[v2.3.9].
– Installation request for nette/application == 2.3.9.0 → satisfiable by
ne
tte/application[v2.3.9].
- Potential causes
- A typo in the package name
- The package is not available in a stable-enough version according to your min
imum-stability setting
see <https://groups.google.com/…c/discussion>
f
or more details.
Read <https://getcomposer.org/…eshooting.md> for further
commo
n problems.
Installation failed, reverting ./composer.json to its original content.
c:\xampp\htdocs\nitransnetteproject>`
- majo1
- Člen | 103
ahoj :)
podarilo sa mi ten doplnok nainstalovat, no teraz pozeram Usage – a tie
dependboxy su riesene tak trocha staticky.
ja potrebujem tahat moznosti do select boxov z databazy, kdezto v tvojom pripade sa rucne definuju:
$form->addDependentSelectBox('city', 'City', array($form["country"]), function ($values) use ($citySlovakia, $cityCzech, $cityUsa) {
$data = new \NasExt\Forms\Controls\DependentSelectBoxData();
if ($values['country'] == 1) {
return $data->setItems($citySlovakia);
} elseif ($values['country'] == 2) {
return $data->setItems($cityCzech);
} elseif ($values['country'] == 3) {
return $data->setItems($cityUsa);
} else {
return $data;
}
})->setPrompt('- Select -');
ci? :)
ja to potrebujem spravit tak, ze ked niekto cez administraciu prida „zastavku“, tak sa automaticky zobrazi aj v select boxe v tomto formulari dostupnom pre navstevnika stranky.
Editoval majo1 (7. 2. 2016 14:45)
- majo1
- Člen | 103
chapem, ja teraz aj vyplnam pole udajmi z db, ale
nemozem vediet, aky udaj pribudne v buducnosti v tabulke a ako ho budem musiet
zapodmienkovat vo addDependentSelectBox :)
viac ma laka opravit aktualny formular, ktory som robil cez pla.nette, kedze
zavislost selectboxov funguje,
potrebujem len vyriesit
- aby sa nenacitalo @layout.latte
- chybu Trying to get property of non-object
public function saveReservationform($reservationform)
25: {
26: $this->database->beginTransaction();
27: $idcust = $this->database->table("customers")->insert($reservationform->custdetail)->idcustomer; // chybu hlasi tracy pri tomto riadku
28: $reservationform->resdetail->customer_idcustomer = $idcust;
29: $this->database->table("reservations")->insert($reservationform->resdetail);
30: $this->database->commit();
31: }
dakujem :)
- premek_k
- Člen | 172
Znovu: Myslím, že by sis měl projít alespoň dokumentaci, abys měl aspoň trochu přehled. Copy&paste programování bez znalosti základů nikam nepovede…
Pokud to přesto chceš zkusit, tak zkus takto:
<?php
$row = $this->database->table("customers")->insert($reservationform->custdetail);
$idcust = $row->idcustomer;
?>
Editoval premek_k (7. 2. 2016 17:27)
- majo1
- Člen | 103
dakujem,
no opat vracia Trying to get property of non-object z riadku $row =
$this->database->table(„customers“)->insert($reservationform->custdetail);
sranda je ta, ze ked som vo formulari nemal tie od seba zavisle select boxy (teda ani $values = $form->getHttpData(); pri ukladani formulara), tak to pekne fungovalo..
- majo1
- Člen | 103
pre upresnenie,
toto je moj model
<?php
namespace App\Model;
use App\Model\BaseManager;
use Nette\Database\Table\IRow;
use Nette\Database\Table\Selection;
use Nette\Utils\ArrayHash;
class ReservationformManager extends BaseManager
{
const
TABLE_NAME = 'reservations',
COLUMN_ID = 'idreservation',
CUSTOMERSTABLE_NAME = 'customers',
CUSTOMERSCOLUMN_ID = 'idcustomer',
SKIBUSTABLE_NAME = 'skibuses',
SKIBUSCOLUMN_ID = 'idskibus',
STATIONTABLE_NAME = 'stations',
STATIONCOLUMN_ID = 'idstation',
CENTERTABLE_NAME = 'centers',
CENTERCOLUMN_ID = 'idcenter';
public function saveReservationform($reservationform)
{
$this->database->beginTransaction();
//$idcust = $this->database->table("customers")->insert($reservationform->custdetail)->idcustomer;
$row = $this->database->table("customers")->insert($reservationform->custdetail);
$idcust = $row->idcustomer;
$reservationform->resdetail->customer_idcustomer = $idcust;
$this->database->table("reservations")->insert($reservationform->resdetail);
$this->database->commit();
}
public function getCenter()
{
return $this->database->table(self::CENTERTABLE_NAME)->order(self::CENTERCOLUMN_ID . ' ASC');
}
public function getStation()
{
return $this->database->table(self::STATIONTABLE_NAME)->order(self::STATIONCOLUMN_ID . ' ASC');
}
public function getStationSel($value)
{
return $this->database->table(self::STATIONTABLE_NAME)->order(self::STATIONCOLUMN_ID . ' DESC')->where('center_idcenter = ?', $value);
//return $this->database->table(self::STATIONTABLE_NAME)->select('CONCAT(city,departureTime) AS spojenyCasMesto')->order(self::STATIONCOLUMN_ID . ' DESC')->where('center_idcenter = ?', $value);
}
public function getSkibus()
{
return $this->database->table(self::SKIBUSTABLE_NAME)->order(self::SKIBUSCOLUMN_ID . ' DESC')->limit(10);
}
public function getSkibusSel($value)
{
return $this->database->table(self::SKIBUSTABLE_NAME)->order(self::SKIBUSCOLUMN_ID . ' DESC')->limit(10)->where('centers_idcenter = ?', $value);
}
}
toto presenter
<?php
namespace App\Presenters;
use App\Model\ReservationformManager;
use App\Presenters\BasePresenter;
use Nette\Application\BadRequestException;
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
use Nette\Database\UniqueConstraintViolationException;
use Tracy\Debugger;
Debugger::enable();
class ReservationformPresenter extends BasePresenter
{
private static $ziskaneIdCentra;
protected $reservationformManager;
public function __construct(ReservationformManager $reservationformManager)
{
parent::__construct();
$this->reservationformManager = $reservationformManager;
}
public function renderDefault()
{
$this->template->_form = $this['reservationForm'];
}
public function handleFirstChange($value)
{
if ($value) {
$resultSk = $this->reservationformManager->getSkibusSel($value);
$secondItems = $resultSk->fetchPairs('idskibus', 'departureDatetime');
$this['reservationForm']['resdetail-skibus_idskibus']->setPrompt('-- vyberte --')
->setItems($secondItems);
$resultSt = $this->reservationformManager->getStationSel($value); //$ziskaneIdCentra
$thirdItems = $resultSt->fetchPairs('idstation', 'city'); //city spojit s casom
$this['reservationForm']['resdetail-station_idstation']->setPrompt('-- vyberte --')
->setItems($thirdItems);
} else {
$this['reservationForm']['resdetail-skibus_idskibus']->setPrompt('-- vyberte najskôr stredisko --')
->setItems(array());
$this['reservationForm']['resdetail-station_idstation']->setPrompt('-- vyberte najskôr stredisko --')
->setItems(array());
}
$this->invalidateControl('secondSnippet');
}
public function handleSecondChange($value)
{
if ($value) {
$resultSt = $this->reservationformManager->getStationSel(); //$ziskaneIdCentra
$thirdItems = $resultSt->fetchPairs('idstation', 'city'); //city spojit s casom
$this['reservationForm']['resdetail-station_idstation']->setPrompt('-- vyberte --')
->setItems($thirdItems);
} else {
$this['reservationForm']['resdetail-station_idstation']->setPrompt('-- najskôr vyberte skibus --')
->setItems(array());
}
$this->invalidateControl('thirdSnippet');
}
protected function createComponentReservationForm()
{
$form = new Form;
$sub1 = $form->addContainer('resdetail');
$sub2 = $form->addContainer('custdetail');
$sub1->addText('numAdult', 'Počet dospelých:')
->addRule(Form::RANGE, 'Musí byť v rozsahu %d až %d', array(0, 100))
->setDefaultValue('0')
->setType('number')->setRequired();
$sub1->addText('numJunior', 'Počet juniorov:')
->addRule(Form::RANGE, 'Musí byť v rozsahu %d až %d', array(0, 100))
->setDefaultValue('0')
->setType('number')->setRequired();
$sub1->addText('numKid', 'Počet detí:')
->addRule(Form::RANGE, 'Musí byť v rozsahu %d až %d', array(0, 100))
->setDefaultValue('0')
->setType('number')->setRequired();
$sub1->addText('numTransportOnly', 'Len doprava:')
->addRule(Form::RANGE, 'Musí byť v rozsahu %d až %d', array(0, 100))
->setDefaultValue('0')
->setType('number')->setRequired();
$resultCe = $this->reservationformManager->getCenter();
$firstItems = $resultCe->fetchPairs('idcenter', 'centerName');
$sub1->addSelect('center_idcenter', 'Stredisko: ', $firstItems)
->setPrompt('-- vyberte --');
$sub1->addSelect('skibus_idskibus', 'Skibus - termín: ')
->setPrompt('-- vyberte najskôr stredisko--');
$sub1->addSelect('station_idstation', 'Zastávka: ')
->setPrompt('-- vyberte najskôr stredisko--');
$sub2->addText('name', 'Meno:')
->setType('text')->setRequired();
$sub2->addText('surename', 'Priezvisko:')
->setType('text')->setRequired();
$sub2->addText('telephone', 'Telefónne číslo:')
->setType('text')->setRequired();
$sub2->addText('email', 'E-mail:');
$form->addProtection('Váš časový limit vypršal. Odošlite prosím formulár znovu.');
$form->addSubmit('submit', 'Rezervovať skibus');
$form->onSuccess[] = [$this, 'editorFormSucceeded'];
return $form;
}
public function editorFormSucceeded($form, $values)
{
try {
$values = $form->getHttpData($form::DATA_LINE | $form::DATA_KEYS, 'resdetail[]');
//$values = $form->getHttpData();
Debugger::barDump($values, 'values insert');
$this->reservationformManager->saveReservationform($values);
$this->flashMessage('Rezervácia bola úspešne odoslaná. Ďakujeme.');
//$this->redirect(':Reservationform:', $values->idreservation);
} catch (UniqueConstraintViolationException $ex) {
$this->flashMessage('Rezervácia s týmto ID už existuje!');
}
}
}
- majo1
- Člen | 103
vymazal som cache a skusil som spravit nasl.:
abstract class BaseManager extends Object
{
protected $database;
public function __construct(Context $database)
{
dump($this->database);
$this->database = $database;
}
}
a tracy pise Possible problem: you are sending a HTTP header while already having some data in output buffer. Try Tracy\OutputDebugger or start session earlier.
ked dam Skip error, tak napise navrchu stranky (pravdepodobne dump): „null“
- premek_k
- Člen | 172
Nejdříve se omlouvám za mé poslední tvrzení, že v tom máš guláš – přehlídl jsem se a neprávem tě osočil. Beru to zpět.
Jinak v metodě editorFormSucceeded
vrať zpět tu konstrukci
$values = $form->getHttpData();
.
Takto bude ve $values array hodnot z formuláře, struktura je
vidět v některém z předchozích tvých příspěvků.
Do modelu do saveReservationForm
tedy předáváš array, proto
s tím musíš i takto pracovat. Třeba takto (když tak si uprav názvy
klíčů toho pole, nevím, jak to tam máš přesně):
<?php
public function saveReservationform($reservationformValues)
{
$this->database->beginTransaction();
$row = $this->database->table("customers")->insert($reservationformValues['custdetail']);
if (!$row){
$this->database->rollback();
return FALSE;
}
$reservationformValues['resdetail']['customer_idcustomer'] = $row->idcustomer;
$row = $this->database->table("reservations")->insert($reservationformValues['resdetail']);
if (!$row){
$this->database->rollback();
return FALSE;
}
$this->database->commit();
return TRUE;
}
?>
Takto by to mělo fungovat. Snad mi něco neuniká, nejsem taky žádný guru, jen se snažím pomoct.
- majo1
- Člen | 103
@premek_k prosím ťa, vedel by si mi ešte poradiť,
ako pri inserte $reservationformValues[‚custdetail‘]
očekovať, či už v tabuľke je daný e-mail a ak je, tak
spraviť iba update?
normálne by som použil ON DUPLICATE KEY UPDATE ale klientov som začal ukladať zo začiatku cez primary key idcustomer, čo je INT inkrementálne. Mal som použiť ako PK nejaký jedinečný údaj ako e-mail.. :/
už to asi pôjde ťažko zmeniť :)
Ďakujem
- premek_k
- Člen | 172
Jednoduše nějak takto:
public function saveReservationform($reservationformValues)
{
$this->database->beginTransaction();
$row = $this->database->table("customers")->where(['email'=> $reservationformValues['custdetail']['email']])->fetch();
if (!$row) {
$row = $this->database->table("customers")->insert($reservationformValues['custdetail']);
}
if (!$row){
$this->database->rollback();
return FALSE;
}
:
:
:
}
- mates
- Člen | 36
premek_k napsal(a):
$this->database->beginTransaction();
$row = $this->database->table(„customers“)->where([‚email‘⇒ $reservationformValues[‚custdetail‘][‚email‘]])->fetch();
if (!$row) {
$row = $this->database->table(„customers“)->insert($reservationformValues[‚custdetail‘]);
}
@premek_k Zajistí ta transakce, že mezi těmi dvěmi příkazy nikdo nevloží nový záznam do tabulky customers? Resp. tabulka customers se v transakci čtením zamkne pro zápis? Standardně, nebo se to tak musí nastavit?