Vlastní form komponenta form->addNeco

pavelinnuendo
Člen | 33
+
0
-

Ahoj,
bojuji s tím, že u form->addText(..) se mi stále opakuje spousta řádků se ->getControlPrototype()->addAttributes() a addRule. Rád bych si proto podědil addText do vlastní komponenty form->addNeco(..), ale nepřišel jsem na to jak.

Vše co jsem dohledal je pro starší Nette a ani to nerozchodil, třeba jako důkaz,
že jsem hledal:
https://forum.nette.org/…addcondition

Mohl bych tedy poprosit o úplně základní kód implementace form->addNeco()?

Děkuji!

Felix
Nette Core | 1189
+
+2
-

Presne jak pises, bud si podedis BaseControl nebo jestli je to primo prace s TextInput, tak rovnou ten. Pokud ale nebudes pridavat extra funkcionalitu, muzes to vsechno vyresit modifikovanim existujiciho TextInputu, nemusis tak vytvaret nove tridy.

Pak mas defacto 2 varianty:

  1. Extension Method
// bootstrap.php
Nette\Utils\ObjectMixin::setExtensionMethod(
    Nette\Forms\Container::class,
    'addMyInput',
    function(Container $container, $name, $title = "My input", $size = 15) {
        return $container[$name] = new MyTextInput($title, $size);
    }
);

class Presenter
{
	protected function createComponentForm()
	{
   		$form = new Form();
    	$form->addMyInput($title = 'Test', $size = 25);
    	return $form;
	}
}
  1. Vlastni form
class MyForm extends Form
{

    public function addMyInput($name, $title = "My input", $size = 15)
    {
        return $this[$name] = new MyTextInput($title, $size);
    }

}

class Presenter
{
	protected function createComponentForm()
	{
   		$form = new MyForm();
    	$form->addMyInput($title = 'Test', $size = 25);
    	return $form;
	}
}

Editoval Felix (11. 8. 2017 23:14)

pavelinnuendo
Člen | 33
+
0
-

Pochopil jsem správně, že metoda createComponentForm() je v objektu MyTextInput?

Pak varianta jedna padá na Missing argument 4 for Nette\Loaders\RobotLoader::App\Forms\{closure}() s
A varianta dvě na Undefined variable: name

Felix
Nette Core | 1189
+
0
-

pavelinnuendo napsal(a):

Pochopil jsem správně, že metoda createComponentForm() je v objektu MyTextInput?

Pak varianta jedna padá na Missing argument 4 for Nette\Loaders\RobotLoader::App\Forms\{closure}() s
A varianta dvě na Undefined variable: name

Malinko tedka nerozumim ke je problem, radeji jsem upravil ukazky jeste. :-)

pavelinnuendo
Člen | 33
+
0
-

Děkuji za trpělivost, ale ještě to je málo. :(

Varianta 1:
Call to a member function addComponent() on string

Varianta 2:
Argument 1 passed to {closure}() must be an instance of Container, instance of Nette\Application\UI\Form given

MyTextINput mám takto:

class MyTextInput extends Nette\Forms\Container {
    protected function createComponentForm()
    {
        $form = new Form();
        $form->addMyInput($title = 'Test', $size = 25);
        return $form;
    }
}

Editoval pavelinnuendo (11. 8. 2017 23:33)

CZechBoY
Člen | 3608
+
+1
-
  • MyTextInput dedi od TextInput.
  • createComponent je v presenteru
  • udelas si svuj form, dedi od Nette\Application\UI\Form, do nej pridas metodu addMyInput
  • v createcomponent v presenteru vytvoris ten svuj form z predchoziho bodu a zavolas metodu addMyInput
pavelinnuendo
Člen | 33
+
0
-

Už se chytám, takto to funguje:

class MyTextInput extends Nette\Forms\Controls\TextInput {
    public function __construct($label, $maxLength)
    {
        parent::__construct($label, $maxLength);
        $this->control->addAttributes([...]);
    }
}

Děkuji vám oběma moc za trpělivost! :)

pavelinnuendo
Člen | 33
+
0
-

A varianta s setExtensionMethod je správně takto (má tam být Form nikoli Container):

Nette\Utils\ObjectMixin::setExtensionMethod(
    Nette\Forms\Container::class,
    'addMyInput',
    function(Nette\Application\UI\Form $form, $name, $title, $size = null) {
        return $form[$name] = new MyTextInput($title, $size);
    }
);
CZechBoY
Člen | 3608
+
0
-

i ten container by mel fungovat, protoze Form dedi od Container.

Felix
Nette Core | 1189
+
0
-

Urcite to funguje na Nette\Form\Container https://api.nette.org/…ntainer.html#…

Felix
Nette Core | 1189
+
+2
-

Nedalo mi to a napsal jsem o tom clanek. :-)

http://bit.ly/2vYAmUJ

CZechBoY
Člen | 3608
+
0
-

@Felix u toho custom formu je jeste mozna technika pres traitu.
Vytvori se trait s addXyz, custom form ktery bude mit prepsanou metodu addContainer vracejici custom container. Form i Container pouzivajici tu traitu.

trait TMyFormControls
{
    pubf addEmail(...){...}

    public function addContainer($name)
     {
         $control = new MyContainer;
         $control->currentGroup = $this->currentGroup;
         if ($this->currentGroup !== null) {
             $this->currentGroup->add($control);
         }
         return $this[$name] = $control;
     }

class CustomForm extends Form
{
    use TMyFormControls;
}
class MyContainer extends Container {
    use TMyFormControls;
}
Felix
Nette Core | 1189
+
0
-

@CZechBoY Diky za napad, prijde mi to uz ale moc. :)

CZechBoY
Člen | 3608
+
0
-

@Felix what? jak jinak chces udelat custom input kterej pude dat do containeru, krome te metody s addComponent.

Editoval CZechBoY (12. 8. 2017 13:58)

Felix
Nette Core | 1189
+
0
-

Nerozumim tedka o cem mluvis. Extension method, addComponent i vlastni form funguji.

CZechBoY
Člen | 3608
+
0
-

Kdyz chci vytvorit vice kontejnerů v jednom formu tak se mi vrati netti container ktery nezna metodu z myho podedenyho formu.