Nefunkční $this->flassmessage() ve FormFactory

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

Zdarec,
už jsem prošel skoro všechno, ale už jsem se do toho nějak zamotal. S Nette víceméně začínám. Snažím se psát formuláře do samostatných souborů jako komponenty, ale nedaří se mi předat zprávu zpátky. Můžete mě, prosím, nakopnout?

App/Forms/UsersFormFactory:

<?php

namespace App\Forms;

use Nette,
    Nette\Application\UI\Form,
    Nette\Security\User,
    App\Forms\Bs3FormRenderer,
    App\Model\UserManager,
    App\Presenters\UsersPresenter;


class UsersFormFactory extends Nette\Object
{
    /** @var Nette\Security\User */
    private $user;
    /** @var App\Model\UserManager */
    private $userManager;


    public function __construct(User $user, UserManager $userManager)
    {
        $this->user = $user;
        $this->userManager = $userManager;
   }

    /**
     *
     * @return Form
     */
    public function create()
    {
        $form = new Form;
        $form->setRenderer(new Bs3FormRenderer);

        $form->addText('username', 'Uživatelské jméno:')
            ->setRequired('Vyplňte uživatelské jméno.');

        $form->addText('firstname', 'Jméno:')
            ->setRequired('Vyplňte uživatelské jméno.');

        $form->addText('surname', 'Příjmení:')
            ->setRequired('Vyplňte uživatelské jméno.');

        $form->addText('email', 'E-mail:')
            ->setRequired('Vyplňte e-mail.')
            ->addRule(Form::EMAIL, 'E-mail není ve správném tvaru.');

        $form->addPassword('password', 'Heslo: ')
            ->setRequired('Vyplňte heslo.');

        $form->addPassword('passwordVerify', 'Heslo pro kontrolu: ')
            ->setRequired('Vyplňte heslo pro kontrolu.')
            ->addRule(Form::EQUAL, 'Hesla se neshodují!', $form['password']);

        $form->addSubmit('send', 'Přidat uživatele');

        $form->onSuccess[] = function (Form $form, \stdClass $values){
            if (!$this->user->isInRole('administrator')) {
                $this->error('Pro vytvoření, nebo editování uživatele musíte být administrátor!');
            }
            $userId = NULL;

            if ($userId) {
                try {
                    $user = $this->database->table('users')->get($postId);
                    $user->update($values);
                } catch (Exception $ex) {
                    $this->flashMessage('Uživatel byl úspěšně změněn!', 'alert-error');
                    $this->redirect('show', $post->id);
                }

            } else {
                try{
                    $this->userManager->insert($form->values);
                }
                catch (Exception $ex) {
                    $this->addError('Chyba!', 'error');
                    $this->redirect('show');
                }
                $this->flashMessage('Uživatel byl úspěšně vytvořen!', 'alert-success');
                $this->redirect('show');
            }


        };

        return $form;
    }

}

ale hlásí to chybu: Call to undefined method App\Forms\UsersFormFactory::flashMessage()

Tuším, že bych si měl asi někde předat nějakou závislost, ale už fakt nevím.
Díky

Oli
Člen | 1215
+
0
-

Komponenta musi dedit z Control. Nette\Object nema metodu flashMessage. Bud poded Control a budes mit vykreslitelnou komponentu, nebo si tu zpravu predej rodici a nech az jeho ji vypsat

Barvoj
Člen | 60
+
+1
-

Osobně bych to řešil přes eventy:

class UsersFormFactory extends Nette\Object
{
    ...

    public $onFormSuccess = [];

    ...

    /**
     *
     * @return Form
     */
    public function create()
    {
        $form = new Form;
        $form->setRenderer(new Bs3FormRenderer);

        ...

        $form->onSuccess[] = function($form) {
            try {
                $this->userManager->insert($form->values);
                $this->onFormSuccess();
            } catch (...) {
                ...
            }
        }

        return $form;
    }

}

A presenter:

class UserPresenter extends Ui\Presenter
{
    /** @inject UsersFormFactory */
    public $formFactory;

    public function createTomponentUsersForm()
    {
        $form = $this->formFactory->create();

        $form->onFormSuccess[] = function() {
            $this->flashMessage('Uživatel byl úspěšně vytvořen!', 'alert-success');
            $this->redirect('show');
        }

        return $form;
    }
}

Ze se ma vypsat flash message a udelat redirect neni vec formulare ale presenteru, tak ho to nech delat..

Ve formulari si vytvor public promenou pole napr $onFormSuccess a diky nette magii pak muzes zavolat methodu stejneho nazvu a nette pak zavola vsechny callbecky ulozene v poli onSuccessForm.

Stejne vlastne funguje onSuccess[] formulare…

Editoval Barvoj (28. 2. 2016 8:09)

Oli
Člen | 1215
+
0
-

Ze se ma vypsat flash message a udelat redirect neni vec formulare ale presenteru, tak ho to nech delat..

S tím úplně nesouhlasím. Redirect, pokud přesměruje sám na sebe může uplně klidně být zodpovědnost formuláře. A hlavně komponenta může mít vlastní flashMessage. FlashMessage je zodpovědností presenteru pouze pokud se jedná o „globální“ zprávu. Můžeš mít ale formulář, odesílat ho ajaxem a chtít zobrazit zprávu hned nad/pod formulářem. V takovým případě patří flashMessage tý komponentě.

Obecně máš ale pravdu, ze většinou to je zodpovědnost presenteru :-)

F.Vesely
Člen | 369
+
+1
-

Ja bych ten event na factory nedaval. Co kdyz budu chtit zobrazit 2× ten samy formular a pokazde udelat neco jineho? Zrovna v tomhle pripade staci, kdyz se v Presenteru navesis na $form->onSuccess.

Pavel Macháň
Člen | 282
+
+4
-

Form Factory má pouze sestavit formulář. Logiku přesuň do komponenty, která pracuje s formulářem.

mario85
Člen | 22
+
0
-

Díky všem za odpovědi.

@Barvoj při tvojem řešení to hlásí chybu Property [ <default> public $formFactory ] has no @var annotation.

@PavelMacháň myslíš přesunout do komponenty celou logiku, kterou teď mám

$form->onSuccess[] = function (Form $form, \stdClass $values){
...
};
mario85
Člen | 22
+
0
-

Tak jsem to celé smazal, vytvořil znova a už to víceméně běží, ale v presenteru se to sekne a hlásí Cannot read an undeclared property Nette\Application\UI\Form::$onFormSuccess. Konkrétně na řádku 62:

59:        public function createComponentUsersForm()
60:        {
61:            $form = $this->usersForm->create();
62:            $form->onFormSuccess[] = function() {
63:                $this->flashMessage('Uživatel byl úspěšně vytvořen!', 'alert-success');
64:                $this->redirect('show');
65:            };
66:            return $form;

Továrnička teď vypadá takhle:

class UsersFormFactory extends Nette\Object
{
    public $onFormSuccess = [];
    private $database;

    public function __construct(Nette\Database\Connection $database)
    {
        $this->database = $database;
    }

    /**
     *
     * @return Form
     */
    public function create()
    {
        $form = new Form;
        $form->setRenderer(new Bs3FormRenderer);

        $form->addText('username', 'Uživatelské jméno:')
            ->setRequired('Vyplňte uživatelské jméno.');

		// ...

        $form->addSubmit('send', 'Přidat uživatele');
        $form->onSuccess[] = function($form) {
            $this->onFormSuccess();
        };

poradí někdo? Předem díky!

premek_k
Člen | 172
+
0
-

Nemá tam v tom presenteru být jen

$form->onSuccess[] = ...

??

mario85
Člen | 22
+
+1
-

premek_k napsal(a):

Nemá tam v tom presenteru být jen

$form->onSuccess[] = ...

??

A jo… Díky moc, už to běhá :-)