Načtení hodnoty do comba pri generovani formulare tovarnou

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
zooner
Člen | 7
+
0
-

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
+
0
-

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
+
+1
-

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.

  1. 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)

zooner
Člen | 7
+
0
-

Super. Diky za pomoc. Strukturu jsem si upravil a nacitani komba funguje. Jen ty hodnoty formulare se porad nenacitaji (napriklad, kdyz spadne validace) :-(

h4kuna
Backer | 740
+
+1
-

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
+
0
-

Ne z databaze. S tim nemam problem. Ale kdyz zakladam novy zaznam a po submitu neprojde validace a nic se neulozi, tak formulare neobsahuji odeslane hodnoty. Ale pokud vlozim formular pomoci {control clientDataForm}, tak tam ty hodnoty jsou.

h4kuna
Backer | 740
+
0
-

Tak zase někde špatně instancuješ form. Nebo špatně plníš data, nebo toho je hodně co děláš blbě. Ukaž kód jak ho máš nyní. Protože když funguje {control clientDataForm}, tak tam motáš s vysokou pravděpodobností další instanci.

zooner
Člen | 7
+
0
-

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;
	}


}

Nahled

Diky moc za, za rady

h4kuna
Backer | 740
+
0
-

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.

  1. 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;
}
  1. 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í
    }
}
  1. 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‘]

  1. 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.
  2. Třídu ClientFormFactory převeď do stavu který jsem posílal prvně.
  3. V ClientFormFactory tuhle konstrukci Model\Countries::$countryList nahraď injektnutím nějakého modelu, fasady a z toho si to vytáhni.
  4. V ClientFormFactory si injektuješ $formFactory ale pak v metodě create ji nepoužiješ, použij ji
  5. ukaž šablonu

Editoval h4kuna (2. 2. 2016 9:22)

zooner
Člen | 7
+
0
-

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">&nbsp;</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">&nbsp;&nbsp;<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">&nbsp;&nbsp;&nbsp;<span class="glyphicon glyphicon-trash"></span>&nbsp;Zrušit&nbsp;&nbsp;&nbsp;</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}
h4kuna
Backer | 740
+
0
-

Šablona vypadá v pohodě. Proč to nejde bude chyba jinde. Napiš mi do zpráv.