Načtení hodnoty do comba pri generovani formulare tovarnou
- zooner
- Člen | 7
Zdravim,
bojuju s formularem, respektive s nacitanim dat do comboboxu. Ve slozce app/forms mam ClientFormFactory.php
class ClientFormFactory extends Nette\Object
{
public function __construct()
{
}
/**
* @return Form
*/
public function create($country = "CZ")
{
$country = strtoupper($country);
$form = new Form();
$form->addProtection('Vypršel časový limit, odešlete formulář znovu');
$form->addText("ClientName", "Název klienta")->setRequired("Zadejte název klienta");
$form->addText("ContactPersonFirstName", "Jméno kontaktní os.")->setRequired("Zadejte kontaktní jméno klienta");
$form->addText("ContactPersonLastName", "Příjmení kontaktní os.")->setRequired("Zadejte kontaktní příjmení klienta");
$form->addText("Email", "Kontaktní email")->setRequired("Zadejte e-mail klienta")->addRule(Form::EMAIL, "E-mail je v nesprávném formátu");
$form->addText("Telephone", "Kontaktní telefon");
$form->addText("ICO", "IČO");
$form->addText("Street", "Ulice a číslo popisné");
$form->addText("ZIP", "PSČ/ZIP")->setRequired("Zadejte PSČ")->addRule(Form::PATTERN, 'PSČ musí mít 5 číslic', '([0-9]\s*){5}');
$form->addText("City", "Město");
$form->addSelect("Country", "Stát", Model\Countries::$countryList)->setPrompt('Zvolte zemi')->setRequired("Zvolte zemi")->setDefaultValue($country);
$form->addText("Note", "Poznámka");
$form->addSubmit("Save", "Uložit");
return $form;
}
}
Tam potrebuji nastavit hodnotu formulare Country.
v presenteru mi metoda createComponentClientDataForm() generuje formular:
class ClientPresenter extends BasePresenter
{
/** @var ClientFormFactory @inject */
public $factory;
private $manager;
public function startup(){
parent::startup();
$this->manager = $this->context->getByType('App\Model\ClientModel');
}
public function beforeRender(){
parent::beforeRender();
// TODO vyuzit getClient()->isAllowed
// if(!$this->getUser()->isAllowed("EXTERNAL")){
// }
}
/**
* Seznam klientu
*/
public function renderDefault()
{
$this->template->clients = $this->manager->findAllClients();
}
protected function createComponentClientDataForm(){
$form = $this->factory->create();
$form->onSuccess[] = $this->formSucceeded;
$this->template->form = $form;
return $form;
}
/**
* Novy klient
*/
public function renderNew(){
}
public function formSucceeded(Nette\Application\UI\Form $form)
{
$action = strtolower($this->getAction());
switch($action) {
case "new":
$client = $this->manager->create($form->getValues());
$this->flashMessage("Klient byl založen", 'success');
$this->redirect('detail', $client->ClientID);
break;
case "detail":
$client = $this->manager->update($form->getValues());
if($client > 0) {
$this->flashMessage("Data klient byla aktualizována", 'success');
}
}
}
/**
* Nahled existujiciho klienta
*
* @param $clientID
*/
public function renderDetail($clientID){
$clientDetail = $this->manager->findClientDetail($clientID);
if(!isset($clientDetail) || $clientDetail == null || empty($clientDetail)){
$this->flashMessage("Požadovaný klient nebyl nalezen", 'danger');
}
$this->factory->create()->getComponent("Country")->setDefaultValue("SK");
$this->template->clientDetail = $clientDetail;
}
}
Data pak nacitam v sablone presenters/templates/Client/detail.latte pomoci
predane promenne $client.
Napr:
<input class="form-control" n:name="ClientName" value="{$clientDetail->ClientName}" placeholder="Zadejte název"/>
Jak nejefektivnejsi nacist hodnotu do comboboxu?
Navic u takto generovaneho formulare mi nezustavaji hodnoty po odeslani. Pokud vsah do sablony vlozim formulare pomoci konstrukce {control clientDataForm}, pak po submitu jsou v polich formulare (vlozeneho {control clientDataForm}) data vyplnena.
Dekuji za odpoved
- Martk
- Člen | 661
Factory:
class ClientFormFactory extends Nette\Object
{
/** @var Entity\Client */
private $clientDetail;
/** @var string */
private $country = 'CZ';
public function __construct() {}
public function setClientDetail(Entity\Client $clientDetail) {
$this->clientDetail = $clientDetail;
return $this;
}
public function setCountry($country) {
$this->country = strtoupper($country);
return $this;
}
/**
* @return Form
*/
public function create()
{
// ...
if ($this->clientDetail) {
$form->setDefaults();
}
return $form;
}
}
V presenteru:
class ClientPresenter extends BasePresenter
{
// ...
/**
* Nahled existujiciho klienta
*
* @param $clientID
*/
public function actionDetail($clientID) {
$clientDetail = $this->manager->findClientDetail($clientID);
$this->factory->setCountry('SK')->setClientDetail($clientDetail);
if(!isset($clientDetail) || $clientDetail == null || empty($clientDetail)){
$this->flashMessage("Požadovaný klient nebyl nalezen", 'danger');
}
$this->template->clientDetail = $clientDetail;
}
protected function createComponentClientDetailForm() {
return $this->factory->create();
}
}
- h4kuna
- Backer | 740
Máš to celkem zamotaný.
Když už máš tvorbu formuláře v Tovární třídě, a používáš DI a dědíš od Nete\Object, tak toho využij.
- Doporučím ti ještě továrnu na samotný instancování Form
class FormFactory
{
public function create()
{
/**
* Možnost později připojit translator, zapnout globalně csrf token, aj.
*/
return new Form;
}
}
ClientFormFactory vytvoří form, a taky se drží metodu na zpracování formu, což bez ní form nefunguje. Jen si přidáš události aby jsi mohl z presenteru reagovat pomocí flash messages.
class ClientFormFactory extends Nette\Object
{
/** @var FormFactory */
private $formFactory;
/** @var \App\Model\ClientModel */
private $manager;
/** @var string */
private $action;
/** @var callable[] */
public $onCreate;
/** @var callable[] */
public $onUpdate;
public function __construct(FormFactory $formFactory, \App\Model\ClientModel $manager)
{
$this->formFactory = $formFactory;
$this->manager = $manager;
}
private function setAction($action)
{
$this->action = strtolower($action);
}
/**
* @return Form
*/
public function create($action, $country = "CZ")
{
$this->setAction($action);
$country = strtoupper($country);
$form = $this->formFactory->create();
$form->addProtection('Vypršel časový limit, odešlete formulář znovu');
$form->addText("ClientName", "Název klienta")->setRequired("Zadejte název klienta");
$form->addText("ContactPersonFirstName", "Jméno kontaktní os.")->setRequired("Zadejte kontaktní jméno klienta");
$form->addText("ContactPersonLastName", "Příjmení kontaktní os.")->setRequired("Zadejte kontaktní příjmení klienta");
$form->addText("Email", "Kontaktní email")->setRequired("Zadejte e-mail klienta")->addRule(Form::EMAIL, "E-mail je v nesprávném formátu");
$form->addText("Telephone", "Kontaktní telefon");
$form->addText("ICO", "IČO");
$form->addText("Street", "Ulice a číslo popisné");
$form->addText("ZIP", "PSČ/ZIP")->setRequired("Zadejte PSČ")->addRule(Form::PATTERN, 'PSČ musí mít 5 číslic', '([0-9]\s*){5}');
$form->addText("City", "Město");
$form->addSelect("Country", "Stát", Model\Countries::$countryList)->setPrompt('Zvolte zemi')->setRequired("Zvolte zemi")->setDefaultValue($country);
$form->addText("Note", "Poznámka");
$form->addSubmit("Save", "Uložit");
$form->onSuccess[] = $this->formSucceeded;
return $form;
}
public function formSucceeded(Nette\Application\UI\Form $form)
{
switch ($this->action) {
case "new":
$client = $this->manager->create($form->getValues());
$this->onCreate($client);
break;
case "detail":
$client = $this->manager->update($form->getValues());
if ($client > 0) {
$this->onUpdate();
}
}
}
}
A presenter se ti velmi smrskne na to nejdůležitější:
class ClientPresenter extends BasePresenter
{
/** @var ClientFormFactory @inject */
public $factory;
/** @var \App\Model\ClientModel @inject */
public $manager;
/**
* Seznam klientu
*/
public function renderDefault()
{
$this->template->clients = $this->manager->findAllClients();
}
protected function createComponentClientDataForm()
{
$form = $this->factory->create($this->action);
$form->onCreate[] = function($client) {
$this->flashMessage("Klient byl založen", 'success');
$this->redirect('detail', $client->ClientID);
};
$form->onUpdate[] = function() {
$this->flashMessage("Data klient byla aktualizována", 'success');
};
return $form;
}
/**
* Nahled existujiciho klienta
*
* @param $clientID
*/
public function renderDetail($clientID)
{
$clientDetail = $this->manager->findClientDetail($clientID);
if (!$clientDetail) {
$this->flashMessage("Požadovaný klient nebyl nalezen", 'danger');
}
$this->getComponent("clientDataForm")->setDefaults(['Country' => "SK"]);
$this->template->clientDetail = $clientDetail;
}
}
V šabloně pro začátek nech form vykreslit automaticky pomocí {control clientDataForm}
Píšu to z hlavy netestuju, měl jsi tam chybu že zbytečně necháváš vytvářet dvě instance formuláře.
Editoval h4kuna (1. 2. 2016 16:14)
- h4kuna
- Backer | 740
Hodnoty formuláře se nenačítají tím myslíš co?
Jakože když ho vykreslíš tak ho nemáš předvyplněný? To si je musíš vytáhnout z databáze a je na to metoda která přijímá pole, kde klíče se musí jmenovat stejně jako jsis pojmenoval prvky.
$form->setDefaults($data);
Si to naplň v té tovární metodě, kde přes metodu create si předej potřebný parametry a předvyplň form.
- zooner
- Člen | 7
Presenter:
class ClientPresenter extends BasePresenter
{
/** @var ClientFormFactory @inject */
public $factory;
/** @var ClientModel @inject */
public $manager;
public function startup(){
parent::startup();
}
// public function beforeRender(){
// parent::beforeRender();
//
// // TODO vyuzit getClient()->isAllowed
//// if(!$this->getUser()->isAllowed("EXTERNAL")){
//
//// }
//
// }
/**
* Seznam klientu
*/
public function renderDefault()
{
$this->template->clients = $this->manager->findAllClients();
}
protected function createComponentClientDataForm(){
$form = $this->factory->create($this->action);
$form->onSuccess[] = $this->formSucceeded;
$this->template->form = $form;
return $form;
}
/**
* Novy klient
*/
public function renderNew(){
}
public function formSucceeded(Nette\Application\UI\Form $form)
{
$action = strtolower($this->getAction());
switch($action) {
case "new":
$client = $this->manager->create($form->getValues());
$this->flashMessage("Klient byl založen", 'success');
$this->redirect('detail', $client->ClientID);
break;
case "detail":
$client = $this->manager->update($form->getValues());
if($client > 0) {
$this->flashMessage("Data klienta byla aktualizována", 'success');
$this->redirect('detail', $this->getParameter("clientID"));
}
}
}
/**
* Nahled existujiciho klienta
*
* @param $clientID
*/
public function renderDetail($clientID){
$clientDetail = $this->manager->findClientDetail($clientID);
if(!isset($clientDetail) || $clientDetail == null || empty($clientDetail)){
$this->flashMessage("Požadovaný klient nebyl nalezen", 'danger');
}
else{
$this->factory->setCountry($clientDetail['Country']);
}
$this->template->clientDetail = $clientDetail;
}
}
ClientFormFactory:
class ClientFormFactory extends Nette\Object
{
/** @var FormFactory */
private $formFactory;
/** @var \App\Model\ClientModel */
private $manager;
/** @var callable[] */
public $onCreate;
/** @var callable[] */
public $onUpdate;
/** @var string */
private $country = 'CZ';
public function __construct(FormFactory $formFactory, ClientModel $manager)
{
$this->formFactory = $formFactory;
$this->manager = $manager;
}
public function setCountry($country) {
$this->country = strtoupper($country);
return $this;
}
/**
* @return Form
*/
public function create()
{
$form = new Form();
$form->addProtection('Vypršel časový limit, odešlete formulář znovu');
$form->addHidden("ClientID");
$form->addText("ClientName", "Název klienta")->setRequired("Zadejte název klienta");
$form->addText("ContactPersonFirstName", "Jméno kontaktní os.")->setRequired("Zadejte kontaktní jméno klienta");
$form->addText("ContactPersonLastName", "Příjmení kontaktní os.")->setRequired("Zadejte kontaktní příjmení klienta");
$form->addText("Email", "Kontaktní email")->setRequired("Zadejte e-mail klienta")->addRule(Form::EMAIL, "E-mail je v nesprávném formátu");
$form->addText("Telephone", "Kontaktní telefon");
$form->addText("ICO", "IČO");
$form->addText("Street", "Ulice a číslo popisné");
$form->addText("ZIP", "PSČ/ZIP")->setRequired("Zadejte PSČ")->addRule(Form::PATTERN, 'PSČ musí mít 5 číslic', '([0-9]\s*){5}');
$form->addText("City", "Město");
$form->addSelect("Country", "Stát", Model\Countries::$countryList)->setPrompt('Zvolte zemi')->setRequired("Zvolte zemi")->setDefaultValue($this->country);
$form->addText("Note", "Poznámka");
$form->addSubmit("Save", "Uložit");
return $form;
}
}
Diky moc za, za rady
- h4kuna
- Backer | 740
Tohle je těžký když ti napíšu že zpracování přesunu do továrný protože to s tím fomulářem souvisí a ty to opět prdneš do presenteru, proč? Asi jsem je napsal nefunkční a nevěděl jsi co tam bylo zapomenuto. Máš to chaoticky napsané, nejprve to potřebuju srovnat, abych našel chybu.
- client detail si ulož do nějaký privátní vlastnosti v presenteru, bude potřeba vícekrát tak ať to pořad nevytahuješ z db
private $clientDetail;
private function createClientDetail($clientID) {
if($this->clientDetail === NULL) {
$this->clientDetail = $this->manager->findClientDetail($clientID);
}
return $this->clientDetail;
}
- Ověření existence detailu přesuň do action, action je místo kde můžeš v případně potřeby vyvolat přesměrování, tj pokud neexistuje detail klienta. Podmínka jde smrsknout.
public function actionDetail($clientID) {
if(!$this->createClientDetail($clientID)){
$this->flashMessage("Požadovaný klient nebyl nalezen", 'danger');
// nějaké přesměrování
}
}
- Nastavení parametru countryId si dej do vytváření továrničky protože bez toho form nemá smysl. Tím ti odpadne
$this->factory->setCountry($clientDetail['Country']);
Ale udělej jako to bylo předtím přes parametr metody factory->create($this->action, $countryId). A do továrničky si to teď dostaneš pomocí vlastnosti $this->clientDetail[‚Country‘]
- Nevím proč tam pořád udržuješ startup když v něm nic není, je to k ničemu akorád zabírá místo.
- Třídu ClientFormFactory převeď do stavu který jsem posílal prvně.
- V ClientFormFactory tuhle konstrukci Model\Countries::$countryList nahraď injektnutím nějakého modelu, fasady a z toho si to vytáhni.
- V ClientFormFactory si injektuješ $formFactory ale pak v metodě create ji nepoužiješ, použij ji
- ukaž šablonu
Editoval h4kuna (2. 2. 2016 9:22)
- zooner
- Člen | 7
Super. Diky za rady.
Sablona:
{* This is the welcome page, you can delete it *}
{block content}
{if $clientDetail}
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary filterable">
<form class="form-horizontal" n:name="clientDataForm">
<div class="panel-heading">
<h3 class="panel-title"> <span class="glyphicon glyphicon-user"> </span>Detail klienta</h3>
</div>
<div class="panel-body">
{*<ul class="error" n:if="$form->errors">*}
{*<li n:foreach="$form->errors as $error">{$error}</li>*}
{*</ul>*}
<div class="col-lg-12">
<h4 class="margin-top"> <b>Obecné informace</b></h4>
<hr>
<div class="col-lg-6">
<input type="hidden" n:name="ClientID" value="{$clientDetail->ClientID}"/>
<div class="form-group">
<label n:name="ClientName" class="control-label col-lg-4">Název klienta</label>
<div class="col-lg-8">
<input class="form-control" n:name="ClientName" value="{$clientDetail->ClientName}" placeholder="Zadejte název"/>
</div>
</div>
<div class="form-group">
<label n:name="ContactPersonFirstName" class="control-label col-lg-4">Jméno kontaktní os.</label>
<div class="col-lg-8">
<input class="form-control" n:name="ContactPersonFirstName" value="{$clientDetail->ContactPersonFirstName}" placeholder="Zadejte název"/>
</div>
</div>
<div class="form-group">
<label n:name="ContactPersonLastName" class="control-label col-lg-4">Příjmení kontaktní os.</label>
<div class="col-lg-8">
<input class="form-control" n:name="ContactPersonLastName" value="{$clientDetail->ContactPersonLastName}" placeholder="Zadejte název"/>
</div>
</div>
<div class="form-group">
<label n:name="Email" class="control-label col-lg-4">Kontaktní email</label>
<div class="col-lg-8">
<input class="form-control" n:name="Email" type="email" value="{$clientDetail->Email}" placeholder="Zadejte název"/>
</div>
</div>
<div class="form-group">
<label n:name="Telephone" class="control-label col-lg-4 ">Kontaktní telefon</label>
<div class="col-lg-8">
<input class="form-control" n:name="Telephone" value="{$clientDetail->Telephone}" placeholder="Zadejte název"/>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label n:name="ICO" class="control-label col-lg-4">IČ</label>
<div class="col-lg-8">
<input class="form-control" n:name="ICO" value="{$clientDetail->ICO}" placeholder="Zadejte název"/>
</div>
</div>
<div class="form-group">
<label n:name="Street" class="control-label col-lg-4">Ulice a číslo popisné</label>
<div class="col-lg-8">
<input class="form-control" n:name="Street" value="{$clientDetail->Street}" placeholder="Zadejte název"/>
</div>
</div>
<div class="form-group">
<label n:name="ZIP" class="control-label col-lg-4">PSČ/ZIP</label>
<div class="col-lg-8">
<input class="form-control" n:name="ZIP" value="{$clientDetail->ZIP}" placeholder="Zadejte název"/>
</div>
</div>
<div class="form-group">
<label n:name="City" class="control-label col-lg-4">Město</label>
<div class="col-lg-8">
<input class="form-control" n:name="City" value="{$clientDetail->City}" placeholder="Zadejte název"/>
</div>
</div>
<div class="form-group">
<label n:name="Country" class="control-label col-lg-4">Stát</label>
<div class="col-lg-8">
<select class="form-control" n:name="Country">
<option value='{$clientDetail->Country}'>Česká republika
<option>Německo
</select>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label n:name="Note" class="control-label col-lg-2">Poznámka</label>
<div class="col-lg-10">
<textarea class="form-control" n:name="Note" rows="3" placeholder="Poznámka">{$clientDetail->Note}</textarea>
</div>
</div>
</div>
</div>
<div class="panel-footer">
<a class="btn btn-default pull-right margin-left" href="ClientList.html"> <span class="glyphicon glyphicon-trash"></span> Zrušit </a>
<button type="submit" class="btn btn-success pull-right" n:name="Save">Uložit</button>
<div class="clearfix">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{/if}
{/block}