Avatar
Raiper34
Redaktor
Avatar
Raiper34:

Zdar,

cely den sa paprem z Nette a za nic na svete nechapem tejto jeden veci... v presenteri vytvorim form

$form = (new EditovatUzivatelaForm($this->database, $this, $this->id))->createee();

potom v tej funkcii createee (test iba preto take prasacke pomenovanie...) urobim

$zaznam = $this->database->table('pouzivatelia')->get($this->id);
$form->setDefaults($zaznam->toArray());

Este tam nastavujem callback na prazdnu funkciu, ktoru chcem otom doplnit, ale otazka je, vykresli sa mi form uplne normalne ale ked nanho kliknem tak mi vyskoci chyba

Call to a member function toArray() on a non-object

Proste na ten riadok:

$form->setDefaults($zaznam->toArray());

Co vobec nechapem lebo pri kliknuti by sa ta funkcia nemala spustat a asi ani nespusta, a pri vykrelsovani sa spusta a funguje... som z toho na nervy uz :-D

Odpovědět 16.8.2015 20:01
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
d4rkw34v3r
Člen
Avatar
Odpovídá na Raiper34
d4rkw34v3r:

Ukaz, jak vypada presenter a ta trida EditovatUziva­telaForm, protoze to resis dost podivne.

Editováno 16.8.2015 20:27
 
Nahoru Odpovědět  +1 16.8.2015 20:27
Avatar
Odpovídá na Raiper34
Martin Konečný (pavelco1998):

Zdar,

obvykle je postup v Nette asi tak následující:

  1. Uděláš si továrničku (factory) na formuláře
use Nette\Security\User,
        Nette\Application\UI\Form;

class SignFormFactory
{

        private $user;

        // závislosti automaticky injectuje DI container

        /**
         * @param User
         */
        public function __construct(User $user)
        {
                $this->user = $user;
        }


        /**
         * @return Form
         */
        public function createSignIn()
        {
                $form = new Form();
                $form->addText("name", "Jméno")
                        ->setRequired("Nezadal jsi jméno");

                $form->addPassword("password", "Heslo")
                        ->setRequired("Nezadal jsi heslo");

                $form->addSubmit("login", "Přihlásit se");
                $form->onSuccess[] = $this->signInSucceeded;

                return $form;
        }


        /**
         * @param Form
         * @param \stdClass
         */
        public function signInSucceeded(Form $form, $values)
        {
                try {
                        // budeš mít nějaký autentikátor s metodou  authenticate(array $credentials)
                        $this->user->login($values->name, $values->password);
                } catch (Nette\InvalidArgumentException $e) {
                        $form->addError($e->getMessage());
                }
        }

}
  1. Tuto továrnu zaregistruješ do configu, aby mohla být injectována
services:
        - SignFormFactory

Díky tomu Nette dokáže automaticky injectovat všechny závislosti (např. objekt třídy Nette\Security\U­ser, který vyžaduješ v konstruktoru).

  1. V presenteru přidáš metodu na vytvoření komponenty
use Nette\Application\UI\Form;

class SignPresenter
{

        /**
         * @var SignFormFactory
         * @inject
         */
        public $signFormFactory;   // aby mohla být automaticky injektována do presenteru, musí být viditelnost public


        /**
         * @return Form
         */
        public function createComponentSignInForm()
        {
                $form = $this->signFormFactory->createSignIn();
                $form->onSuccess[] = function(Form $form) {
                        $p = $form->getPresenter();
                        $p->flashMessage("Byl jsi úspěšně přihlášen");
                        $p->redirect("User:overview");
                };

                return $form;
        }

}
  1. Vykreslíš komponentu v šabloně
{block content}

<h1>Přihlášení</h1>

{control signInForm}

{/block}

Dodatek:
Pokud chceš předávat formuláři defaultní data, je k tomu určena metoda action() v presenteru.

public function actionSignIn()
{
        // ke komponentě se dostaneš speciálním zápisem $this["nazev_komponenty"]
        $this["signInForm"]->setDefaults(array(
                "name" => "předvyplněné jméno"
        ));
}
Akceptované řešení
+20 Zkušeností
Řešení problému
 
Nahoru Odpovědět  +1 16.8.2015 20:51
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Raiper34
Jindřich Máca:

Souhlasím s d4rkw34v3r, opravdu to řešíš dost podivně. Nicméně ta chyba je způsobena následující příčinou:

  • Kliknutí na formulář ho odešla na stejnou stránku.
  • Aby mohl být formulář správně zvalidován a předán do funkce pro jeho zpracování, tak se musí znovu zkonstruovat. Přeci si nebudeš držet jeho instanci pro každého uživatele, který s ním zrovna pracuje. Ne, Ty si ho znova zhotovíš, doplníš do něj odeslané hodnoty a pak ho předáš k dalšímu zpracování.
  • A samozřejmě, aby vše bylo konzistentní, tak se formulář vytváří úplně stejným způsobem jako při jeho vytvoření pro stránku, pouze se pak již nerenderuje.

Vualá, tady je Tvoje druhé volání metody createee(), které nevíš odkud se vzalo. A samozřejmě když ho pak voláš podruhé, pravděpodobně se mu předává špatné $this->id, poté následné volání databáze s neplatným ID vrátí hodnotu false a jak už jsi asi pochopil, false není objekt, tudíž na něj nemůžeš logicky volat metodu toArray(). A jsme doma! :D

Co se týče správného řešení, na to bych musel vidět mnohem více kódu, ale obecný postup zde již dobře popsal Martin Konečný (pavelco1998). :)

Editováno 16.8.2015 20:56
 
Nahoru Odpovědět  +1 16.8.2015 20:53
Avatar
Raiper34
Redaktor
Avatar
Raiper34:

Tak ja to mam cca tak ako napisal Martin... ale stale akosi nechapem kde je ta chyba, predsa id som predal konstuktoru a v tom objekte je ulozene to id stale neprepisuje sa nic a ked sa znovu zavola mal by tam byt stale to iste idcko. Ja to potrebuje iba na to aby som dal do formu defaulne hodnoty z databaze...

Nahoru Odpovědět 16.8.2015 22:09
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Raiper34
Jindřich Máca:

Tak to se dělá přesně tak, jak psal Martin Konečný (pavelco1998).

Pokud chceš předávat formuláři defaultní data, je k tomu určena metoda action() v presenteru.

public function actionSignIn()
{
        // ke komponentě se dostaneš speciálním zápisem $this["nazev_komponenty"]
        $this["signInForm"]->setDefaults(array(
                "name" => "předvyplněné jméno"
        ));
}
 
Nahoru Odpovědět  +1 16.8.2015 22:14
Avatar
Raiper34
Redaktor
Avatar
Raiper34:

No ale aj tak mi to nefunguje :/ V editovanie Presenter mam

protected function createComponentEditovanieForm()
        {
                $form = (new EditovatUzivatelaForm($this->database))->createee();
                return $form;
        }

        public function actionEditovanieForm()
        {
                $zaznam = $this->database->table('pouzivatelia')->get($this->id);
                $this["EditovatUzivatelaForm"]->setDefaults($zaznam->toArray());
                $this["EditovatUzivatelaForm"]->id = $this->id;
        }

teraz mi to nenaplni ani to id cez public atributu na skusku co som urobil...

Nahoru Odpovědět 16.8.2015 23:59
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Raiper34
Jindřich Máca:

No, jelikož ta metoda action*() by se měla vztahovat k akci presenteru, kde voláš ten formulář a ne k tomu formuláři samotnému... :-D

Zrovna tuhle problematiku jsem už 2x řešil v tutoriálu pro Nette, který zde aktuálně píšu. Nechci se nijak propagovat, ale myslím, že jeho přečtení by Ti opravdu pomohlo. :) Konkrétně se to řeší v tomto díle http://www.itnetwork.cz/…administrace. Je zde přímo ukázka editačního formuláře pro články a jak ho naplnit výchozími hodnotami. K článku jsou navíc i kompletní zdrojové kódy ke stažení. ;)

 
Nahoru Odpovědět  +1 17.8.2015 0:36
Avatar
Raiper34
Redaktor
Avatar
Raiper34:

No nieco som urobil ale zase sa objavili ine problemy :-D btw maju sa aj form factory pomenovavat menoFormFactory? ako je to pri presenteroch menoPresenter? Lebo moje factory sa volaju iba menoForm

Nahoru Odpovědět 17.8.2015 12:29
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Raiper34
Redaktor
Avatar
Raiper34:

Este otazka, ked mam renderDefault, a ako hovoris ze by sa to malo stahovat k akii presneteru v tomto pripade actionDefault? Alebo som uplne mimo? :-D precital som 7 dielov tych nette clankov, ale stale som na tom mojom probleme zaseknuty :-D

Nahoru Odpovědět 17.8.2015 12:48
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Raiper34
Redaktor
Avatar
Raiper34:

Ten form mi nenajde ked sa snazim naplnit data :/
Toto mam

protected function createComponentEditovanieForm()
        {
                $form = (new EditovatUzivatelaForm($this->database))->createee();
                return $form;
        }

        public function actionDefault($id)
        {
                $zaznam = $this->database->table('pouzivatelia')->get($this->id);
                $this["EditovanieForm"]->setDefaults($zaznam->toArray());
                $this["EditovanieForm"]->id = $this->id;
        }

takto to amm zaregistrovane v config

services:
        authenticator: App\Model\Prihlasovanie
        router: App\Router::vytvoritRouter
        - App\Forms\EditovatUzivatelaForm

Co robim zle? Uz vobec neviem

Nahoru Odpovědět 18.8.2015 15:05
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Raiper34
Jindřich Máca:

Pojmenování těchto tříd je asi čistě na Tobě. :) Já tam třeba to FormFactory většinou píšu. ;)

 
Nahoru Odpovědět  +1 18.8.2015 15:23
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Raiper34
Jindřich Máca:

Ano, pochopil jsi to dobře, pokud se ten formulář vykresluje v default, tak by se to mělo vztahovat k actionDefault(). :)

 
Nahoru Odpovědět  +1 18.8.2015 15:25
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Raiper34
Jindřich Máca:

Můžu se zeptat, kde bereš to $this->id ? Protože pokud nemáš nadefinovanou třídní proměnou $id a nenaplníš jí před vykonáním actionDefault(), v tomhle případě jedině v metodě startup(), tak to $this->id je v době, kdy ho tam voláš null. :D Tam by totiž mělo být jenom to $id, které dostáváš jako parametr té funkce actionDefault($id). :)

 
Nahoru Odpovědět  +1 18.8.2015 15:29
Avatar
Raiper34
Redaktor
Avatar
Raiper34:

To this ide je moja chyba hej, lebo v renderi som najprv naplnal to id tej tiredy a potom vyuzival, potom to hlasilo chybu zze aj action potrebuje mat tolko isto parametrov ako render... ale ono mi to robi to ze ten form nenajde, ze neexistuje taky form ked sa tam snazim predat data

Nahoru Odpovědět 18.8.2015 15:57
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Raiper34
Jindřich Máca:

To bude asi tím, že název toho formuláře má začínat malým písmenem tj. editovanieForm, stejně jako když to píšeš to Latte makra control. ;)

 
Nahoru Odpovědět  +1 18.8.2015 16:12
Avatar
Raiper34
Redaktor
Avatar
Raiper34:

Nah diky :)

Nahoru Odpovědět 18.8.2015 17:20
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 17 zpráv z 17.