i have a doubt about separate classes forms

Notice: This thread is very old.
alnux
Member | 106
+
0
-

How can i do a separate forms classes and call them to my presenters. Example login form that is used on users access and admin panel. This for avoid write same code on differents scripts.

Jan Endel
Member | 1016
+
-4
-

Its simple.

Form can be implemented like this:

class LoginForm extends Nette\Application\UI\Form
{
	/**
	 * @var IAuthenticator
	 */
	private $authenticator;



	public function __construct(IAuthenticator $authenticator)
	{
		$this->authenticator = $authenticator;

		$this->addText('name', 'Name:')
			->setRequired('Name is required');

		$this->addPassword('password', 'Password')
			->setRequired('Password is required');

		$this->addSubmit('send');
		$this->onSuccess[] = function (LoginForm $form) {
			$values = $form->getValues();
			$this->authenticator->login($values->name, $values->password);
		}
	}
}



interface ILoginFormFactory
{
	/**
	 * @return LoginForm
	 */
	function create();
}

and presenter

namespace FrontModule;



class LoginPresenter extends Nette\Application\UI\Presenter
{
	protected function createComponentLoginForm(ILoginFormFactory $factory)
	{
		$form = $factory->create();
		$form->onSuccess[] = function () {
			$this->flashMessage('Login successfull', 'success');
		}
	}
}

and for admins:

namespace AdminModule;



class LoginPresenter extends Nette\Application\UI\Presenter
{
	protected function createComponentLoginForm(ILoginFormFactory $factory)
	{
		$form = $factory->create();
		$form->onSuccess[] = function () {
			if (!$this->user->isInRole('admin')) {
				$this->flassMessage('You cannot access this page');
				$this->redirect(':Front:Default:')
			}

			$this->flashMessage('Login successfull', 'success');
		}
	}
}
Majkl578
Moderator | 1364
+
+2
-

Extending Form class is antipattern, instead, use factory classes where you build your form and return it.

alnux
Member | 106
+
0
-

I cant find docs for factory. What about components and control? There say that i can make forms as components but i dont undertand it.

Majkl578
Moderator | 1364
+
+4
-

There is nice article on the forum, sadly only in czech, but concept should be clear.


What about components and control? There say that i can make forms as components but i dont undertand it.

That probably means you can encapsulate a form within a control, e.g. you create LoginControl which contains only form definition and form rendering. Simply put, something like:

class FooControl extends UI\Control
{
	public function render()
	{
		$this['form']->render();
	}

	protected function createComponentForm()
	{
		$form = new UI\Form();
		...
		return $form;
	}
}
Jan Endel
Member | 1016
+
0
-

Can @Majkl578 describe me, why is extending form class antipatern?

Felix
Nette Core | 1078
+
0
-

Extends form is not antipattern in case of adding new inputs/controls, behaviour etc. For example

  • $form->addDatePicker()
  • $form->addDateTimePicker()
  • etc..

Last edited by Felix (2014-06-22 16:15)

Majkl578
Moderator | 1364
+
0
-

Jan Endel wrote:

Can @Majkl578 describe me, why is extending form class antipatern?

Yes. It is an abuse of inheritance. Inheritance in OOP should extend functionality in terms of behavior. Similar situation – would you extend DateTime to set current time and time zone?
But please, read the referenced topic first before starting offtopic here.

alnux
Member | 106
+
0
-

Majkl578 wrote:

Jan Endel wrote:

Can @Majkl578 describe me, why is extending form class antipatern?

Yes. It is an abuse of inheritance. Inheritance in OOP should extend functionality in terms of behavior. Similar situation – would you extend DateTime to set current time and time zone?
But please, read the referenced topic first before starting offtopic here.

Now i understand your point, that is the way why david develop that (in the post you suggest me) ja ja ja the way that Jan Endel suggest is more easy (by the way thanks too to Jan Endel)

Majkl578
Moderator | 1364
+
0
-

Felix wrote:

Extends form is not antipattern in case of adding new inputs/controls, behaviour etc.

Missed your comment – yes, of course, if you are adding new such methods, then yes. But not building form within itself.

alnux
Member | 106
+
0
-

Majkl578 wrote:

Felix wrote:

Extends form is not antipattern in case of adding new inputs/controls, behaviour etc.

Missed your comment – yes, of course, if you are adding new such methods, then yes. But not building form within itself.

Majkl578 i solved it based on david topic bu calling just one service to many Forms. It for all developers that want do the same.

config.neon

services:
    formContainer: App\Libs\Containers\FormContainer

FormContainer.php

<?php

namespace App\Libs\Containers;

use \Nette\Application\UI\Form;

use App\Libs\Forms as Frm;

class FormContainer
{

    public function getLoginForm()
    {
    	return new Frm\LoginForm();
    }
}

HomePresenter.php calling example

<?php
namespace App\Presenters;

use Nette,
	\Nette\Application\UI\Form;
use App\Libs\Forms\LoginForm;


class HomePresenter extends BasePresenter
{

	/** @inject @var \App\Libs\Containers\FormContainer */
    public $form;

	public function renderDefault()
	{

	}


	protected function createComponentLoginForm()
	{

        $loginForm = $this->form->getLoginForm();
        $loginForm->setTranslator($this->translator);
        return $loginForm->build();

    }
}

LoginForm.php

<?php

namespace App\Libs\Forms;

class LoginForm extends BaseForms
{

	public function build()
	{

		$this->form->addProtection('formerrors.formvalidate');
		$this->form->addGroup('Personal data');
		$this->form->addText('username', 'forms.login.username')->setRequired('formerrors.required.username');
        $this->form->addPassword('password', 'forms.login.password')->setRequired('formerrors.required.password');

        $this->form->addSubmit('sub', 'forms.login.login');

        $this->form->onSuccess[] = callback($this, 'process');

        return $this->form;

	}

}

and finally BaseForm.php

<?php

namespace App\Libs\Forms;

use \Nette\Application\UI\Form,
	\Nette\Object;

use App\Libs\Containers\FormContainer;

class BaseForms extends Object
{

	protected $values;

	protected $form;

	public function __construct()
    {
        $this->form = new Form;
    }

    public function setTranslator($translator)
    {
    	$this->form->setTranslator($translator);
    }

    public function process()
	{
	    $this->values = $this->form->getValues();

	    echo $this->values->username;
    }
}

Last edited by alnux (2014-06-23 00:25)

Jan Endel
Member | 1016
+
0
-

Ok @Majkl578, it make sense for me. I will start to write it this way.