formulář jako vlastní komponenta

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

Chtěl bych se zeptat jak tvořit formuláře jako komponenty.
Nenašel jsem žádné aktuální řešení. Psal jsem formuláře pomocí createComponent továrniček v presenteru, ale časem se jich naskládá hodně a presenter je plný továrniček na komponenty a metody jsou dost rozsáhlé.
Narazil jsem na to, že ostatní programátoři si vytvoří v adresáři App složku Forms a tam vkládají formuláře.
Je to správné řešení? Můžete mně pomoct s jeho implementací?

Forms/AddCustomerForm

<?php

namespace App\Forms;

use Nette\Application\UI\Control;
use Nette\Application\UI\Form;

class AddCustomerForm extends UI\Control{

    public function render()
    {
        $this->template->form = $this->createComponentAddCustomerForm();
    }


    protected function createComponentAddCustomerForm()
    {
        $form = new UI\Form;
        $form->addText("company","Firma/Osv1č")->setAttribute("class","textField form-control")->setRequired();
        $form->addText("ic","IČ")->setAttribute("class","textField form-control")->addRule($form::INTEGER);
        $form->addText("dic","DIČ")->setAttribute("class","textField form-control")->addRule($form::INTEGER);
        $form->addText("email","email")->setAttribute("class","textField form-control")->addRule($form::EMAIL,"Zadejte platný email.")->setRequired();
        $form->addText("phone","telefon")->setAttribute("class","textField form-control")->setRequired();
        $form->addSubmit("submit","Přidat záznam")->setAttribute("class","submitButton btn btn-default");
        $form->onSuccess[] = array($this, 'addCustomerFormSubmitted');
        return $form;
    }

    public function AddCustomerFormSubmitted(UI\Form $form)
    {
        $values = $form->getValues();
        try{
            $id = $this->database->table("client")->insert(array("cID"=>NULL,"company"=>$values->firmaOsvc,"ic"=> $values->ic,"dic"=>$values->dic,"email"=>$values->email,"phone"=>$values->telefon));
            $this->flashMessage('Zákazník byl vložen. Bylo mu přiděleno id '.$id);
        }catch(Exception $e){
            $this->flashMessage('Nastala výjimka: '.$e);
        }
    }


}

Presenter

use App\Forms;

..

public function renderDefault()
{
	$this->template->form = new AddCustomerForm();
}

..

Debugger vyhazuje chybu Class ‚App\AddCustomerForm‘ not found.
Nevítě někdo čím to je? a jestli je správné takto řešit formuláře?

Pavel Macháň
Člen | 282
+
0
-

ondrakrajcik napsal(a):

Chtěl bych se zeptat jak tvořit formuláře jako komponenty.
Nenašel jsem žádné aktuální řešení. Psal jsem formuláře pomocí createComponent továrniček v presenteru, ale časem se jich naskládá hodně a presenter je plný továrniček na komponenty a metody jsou dost rozsáhlé.
Narazil jsem na to, že ostatní programátoři si vytvoří v adresáři App složku Forms a tam vkládají formuláře.
Je to správné řešení? Můžete mně pomoct s jeho implementací?


Debugger vyhazuje chybu Class ‚App\AddCustomerForm‘ not found.
Nevítě někdo čím to je? a jestli je správné takto řešit formuláře?

Vytvoříš si třídu, která má zděděný UI\Form kde si ho sestavíš ($this->addText(…)). Dále si vytvoříš továrničku, kterou necháš injectnout do prezenteru a v createComponent pomocí továrničky ten form vytvoříš

MyForm:

class MyForm extends \Nette\Application\UI\Form {

    public function __construct() {
        parent::__construct();
        $this->buildForm();
    }

    /** @return Form */
    public function buildForm() {
        $this->addProtection();
        $this->addText('text', 'Text:');
        $this->addSubmit('send', 'Odeslat');
        $this->onSuccess[] = $this->processForm;
    }
}

Továrnička

interface IMyFormFactory{

    /** @return MyForm */
    public function create();

}

Config

services:
	- IMyFormFactory

Presenter

class MyPresenter extends \Nette\Application\UI\Presenter {

    /** @var IMyFormFactory @inject */
    public $myFormFactory;

    /** @return MyForm */
    public function createComponentMujForm() {
         return $this->myFormFactory->create();
    }
}

Editoval EIFEL (8. 3. 2014 18:17)

David Matějka
Moderator | 6445
+
0
-
  1. mas problem s namespace, bud v use uved App\Forms\AddCustomerForm nebo musis v new Forms\AddCusomerForm
  2. udelej si generovanou tovarnicku
  3. injectni si zavislosti (database atd)
  4. spatne pouzivas komponenty, viz https://doc.nette.org/…n/presenters#…

cely priklad, jak obalit form UI\Control-em najdes tady:
https://doc.nette.org/…s/form-reuse#…

Editoval matej21 (8. 3. 2014 18:48)

Šaman
Člen | 2632
+
0
-

Funkční ukázku nad aktuálním Nette mám na GitHubu.
Třída komponenty a šablona jsou jasné. Rozhraní je potřeba, pokud chceš používat generovanou továrničku v configu. A pokud ano, tak to, co je v souboru s traitou TCreateComponent… patří do presenteru a to je vše.

ondrakrajcik
Člen | 45
+
0
-

Potřebuju se ještě zeptat, rozšiřuju formulář, který jsem zde uvedl, tak aby ho mohl využívat zároveň pro vkládání tak i pro editaci.

ořezaně to vypadá takto

class MyForm extends \Nette\Application\UI\Form {

    public function __construct() {
        parent::__construct();
        $this->buildForm();
    }

    /** @return Form */
    public function buildForm() {
        $this->addProtection();
        $this->addText('text', 'Text:');
        $this->addSubmit('send', 'Odeslat');
        $this->setAction($this->getPresenter()->link('this', array('id' => 1, 'do' => 'addClientFormSubmitted'))); // tento radek jsem pridal a dělá potíže
        $this->onSuccess[] = $this->processForm;
    }
}

Pokud jsem stejný způsob použil v presenteru v továrničce tak to funguje, ale takto když formulář mám jako komponentu, tak debugger vyhazuje chybu

Component '' is not attached to ‚Nette\Application\UI\Presenter‘

David Matějka
Moderator | 6445
+
0
-

komponenta/formular neni v konstruktoru pripojen k presenteru (maximalne pokud bys ho pripojil rucne), zkus:

class MyForm extends UI\Form {
	public function attached($presenter)
	{
		parent::attached($presenter);
		if($presenter instanceof UI\Presenter) {
			$this->buildForm();
		}
	}
}

(konstruktor smaz)

ale lepsi je formular jako komponenta. nebo co ti na tom nevyhovovalo?

btw, to rucni nastavovani action bys delat nemel…

Editoval matej21 (26. 3. 2014 18:27)

ondrakrajcik
Člen | 45
+
0
-

matej21 napsal(a):

komponenta/formular neni v konstruktoru pripojen k presenteru (maximalne pokud bys ho pripojil rucne), zkus:

class MyForm extends UI\Form {
	public function attached($presenter)
	{
		parent::attached($presenter);
		if($presenter instanceof UI\Presenter) {
			$this->buildForm();
		}
	}
}

(konstruktor smaz)

ale lepsi je formular jako komponenta. nebo co ti na tom nevyhovovalo?

btw, to rucni nastavovani action bys delat nemel…

Pokud by se to ruční nastavování action dělat nemělo, tak jak se správně dá použít formulář zároveň pro editaci a zároveň pro vkládání záznamů?

David Matějka
Moderator | 6445
+
0
-

bud se rozhodnes ve zpracovani, viz https://doc.nette.org/…editing-form#…
nebo treba prislusny callback nastavis v action* metode

public function actionNew()
{
	$this['form']->onSuccess[] = $this->createSth;
}

public function actionEdit()
{
	$this['form']->onSuccess[] = $this->editSth;
}