zprovoznění formuláře v šabloně → uplný začátečník

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

Zdravím všechny, jelikož jsem slyšel na nette samou chválu, rozhodl jsem se, že se to taky naučím. Posledních pár dní po večerech tedy studuji.. Mám však problém rozchodit i základní věci, které v php normálně zvládám :(
Stáhl jsem si nette 2 beta, poté jsem vytvořil statický web podle tutoriálu „Statický web s menu“, což jsem zmákl, pak jsem chtěl podle dalšího vytvořit formulář se zasíláním na mejl, to už se mi nepovedlo.. Autor používá 2 alpha, je tento tutoriál funkční?
Pustil jsem se tedy podle dokumentace do vytváření vlastního řešení..
do homepage presenteru jsem tedy přidal:

<?php
protected function createComponentForm()
{
    $form = new Nette\Application\UI\Form;
    $form->addText('name', 'Jméno:');
    $form->addText('email', 'Email:');
    $form->addTextarea('note', 'Poznamka');
    $form->onSuccess[] = callback($this, 'signInFormSubmitted');
    return $form;
}

?>

do šablony contact.latte

<?php
{control Form}
?>

Laděnka píše: „Component with name ‚Form‘ does not exist“

Já si však myslím, že tu komponentu jsem vytvořil v tom presenteru, ne?
Děkuji za každou radu!! :)

chuck_horis
Člen | 8
+
0
-

Děkuji za pomoc, už jsem to oživil :)

chuck_horis
Člen | 8
+
0
-

Tak další den a další pokus s nette :)
Nechápu asi jednu věc, pokud si čtu např návod jako na formuláře nebo databaze s nette, kam mám tento kod kopírovat? Jedná se mi o to, že když ho dám do šablony nic se nedeje a kod se vypíše jako text.. Proto jsem kod dal do pressenteru. Kam tedy kopírovat ukázky kodů? Do šablon ?

Snažil jsem se rozchodit validaci:

<?php
protected function createComponentForm()
{
    $form = new Nette\Application\UI\Form;
    $form->addText('name', 'Name:')
    ->addRule(Form::FILLED, 'Zadejte jméno');
    $form->addText('email', 'Email:')
    ->addRule(Form::EMAIL, 'Zadejte jméno');
    $form->addTextarea('note', 'Note:')
    ->addRule(Form::FILLED, 'Vyplnte poznámku!');
    $form->addSubmit('send', 'Odeslat');
            return $form;
}
?>

Samozřejmě, laděnka mi píše že class "Form ",takžeje potřeba jí vytvořit nebo vložit? Vím že se tam nemá psát Nette\Forms\Form ale Nette\Application\UI\Form, když je to v presenteru :\ Stejně tak nevím jak vložit javascript validaci :\

Dále bych rád pokračoval s odesláním na mejl, takže pokud doplním

<?php
$form->onSubmitted[] = 'FormSubmitted';
?>

A pak vytvořím komponentu Formsubmitted bude to dobře, ano? Musím říct, že fakt strašně tápu i v základní logice:\ Díky za pomoc!

Editoval chuck_horis (10. 11. 2011 13:32)

Filip Procházka
Moderator | 4668
+
0
-

Ono kdyby jsi si pročetl tu dokumentaci i 2×, tak se třeba lépe chytneš. A evidentně máš také problémy se základy PHP, které by jsi si měl doplnit!

chuck_horis napsal(a):

Nechápu asi jednu věc, pokud si čtu např návod jako na formuláře nebo databaze s nette, kam mám tento kod kopírovat? Jedná se mi o to, že když ho dám do šablony nic se nedeje a kod se vypíše jako text.. Proto jsem kod dal do pressenteru. Kam tedy kopírovat ukázky kodů? Do šablon ?

Ideálně nekopírovat, ale jen na něj kouknout a napsat ho sám. Dříve si zapamatuješ API. Do šablony se kopírují šablony a PHP kód se kopíruje většinou do presenterů, nebo vlastních tříd, které vhodně umístíš v adresáři app/ (třeba do app/models/NejakaTrida.php).

Snažil jsem se rozchodit validaci:

protected function createComponentForm()
{
    $form = new Nette\Application\UI\Form;
    $form->addText('name', 'Name:')
	    ->addRule(Form::FILLED, 'Zadejte jméno');
    $form->addText('email', 'Email:')
	    ->addRule(Form::EMAIL, 'Zadejte email');
    $form->addTextarea('note', 'Note:')
    	->addRule(Form::FILLED, 'Vyplňte poznámku!');

    $form->addSubmit('send', 'Odeslat');
    $form->onSuccess[] = callback($this, 'signInFormSubmitted');

    return $form;
}

Samozřejmě, laděnka mi píše že class "Form ",takžeje potřeba jí vytvořit nebo vložit?

Tuhle větu se nebudu snažit pochopit.

Vím že se tam nemá psát Nette\Forms\Form ale Nette\Application\UI\Form, když je to v presenteru.

Vidíš, aspoň něco :)

Stejně tak nevím jak vložit javascript validaci :\

Nijak, ty pravidla Nette uloží k formulářovým prvkům samo. Ty musíš jenom do hlavičky layoutu nakopírovat „přilinkování“ javascriptu, který je bude kontrolovat. Hledej nette.forms.js.

Dále bych rád pokračoval s odesláním na mejl, takže pokud doplním

Odeslání na „mejl“ se dělá pomocí Nette\Mail\Message.

<?php
$form->onSubmitted[] = 'FormSubmitted';
?>

A pak vytvořím komponentu Formsubmitted bude to dobře, ano?

Rozhodně to nebude dobře, dobře to bylo předtím. Tohle není žádná komponenta, ale callback, který se má zavolat, pokud je formulář odeslán validně.

Takže opravit na

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

A do téhle metody presenteru

public function signInFormSubmitted($form) { ...

si pak vložíš svoje zpracování, nebo odesílání na email, podle dokumentace.

Příště, až budeš psát příspěvek na fórum, tak než klikneš na tlačítko odeslat, běž ještě jednou se podívat na kód a po řádku ho projdi. Protože mi to přijde, že jsi zkopírovat pár věcí z dokumentace, slepil je dohromady a divíš se, že to nefunguje.

ZAJDAN
Člen | 45
+
0
-

tak nettíci tady si lámu hlavu i já…nastala chvíle kdy potřebuju vytvořit formulář a vykreslit v šabloně ovšem něco je špatně.
vytvořili jsme si presenter Registration.Presenter.php

<?php
use Nette\Forms\Form;
class RegistrationPresenter extends BasePresenter {

    public function renderDefault() {
          $template->signInForm = $this->createComponentSignInForm();
        if(!Nette\Environment::isProduction()) {
            $this->stubData();
        }
    }

    protected function createComponentSignInForm() {
    $form = new Form;
    $form->setAction('/submit.php');
    $form->setMethod('GET');

    $form->addText('name', 'Jméno:');
    $form->addText('adresse','adresa:');

    $regions = array(
        '1' => 'Jihočeský',
        '2' => 'Jihomoravský',
        '3' => 'Karlovarský',
    );


    $form->addSelect('regions','Kraj:', $regions)
        ->setPrompt('Zvolte Kraj');

    $form->addText('city','Město:');
    $form->addText('email','email:');
    $form->addText('phone1','Telefon č.1:');
    $form->addText('phone2','Telefon č.2:');
    $form->addText('web','WWW:');


    return $form;
}
public function signInFormSubmitted($form)
{
    //  po odeslání formuláře
}


    public function addService($name, $service) {

    }
    public function hasService($name) {

    }
    public function removeService($name) {

    }

    /**
     * Stub data for development purpose only.
     */
    public function stubData() {

    }
}

?>

dále jsme si vytvořili šablonu \templates\Registration\default.latte

{form form}
<table>
<tr class="required">
    <th>{label name /}</th>
    <td>{input name}</td>
</tr>
...
</table>
{/form form}

ovšem dostávám hlášku:
reating default object from empty value
kde mu vadí na řádku 11
11: $template->signInForm = $this->createComponentSignInForm();
a tady si nejsem jistý, zda takto je to správně – renderovat form do šablony

Editoval ZAJDAN (3. 3. 2012 16:05)

Jan Endel
Člen | 1016
+
0
-

Nevím kde začít první, ale zkusím to od vrchu dolů:

  1. takhle se továrnička nevolá v renderDefault rozhodně nevolá
  2. Environment je fujík, použij raději:
if ($this->context->parameters['productionMode'] === false)
  1. Sign In je přihlašovací formulář, Sign Up je registrační
  2. Formuláři nedáváme v Nette presenterech akci takto, ale přidáme mu callback:
$form->onSuccess[] = callback($this, 'signInFormSubmitted');
  1. Pokud už to je tedy registrační formulář, doporučuju prvkům přidat "validační pravidla"https://doc.nette.org/cs/forms#toc-validace :
$form->addText('name', 'Jméno:')
	->setRequired('Zadejte prosím své jméno.');
  1. Předpokládám, že používáš Netbeans 7.1, je v nich u Nette takový malý bug, že podtrhuje červeně název třídy i když je správně (protože mu prý chybí implementace metod z IContainer). Takže klidně metody addService, hasService a remoteService odmaž.
  2. Formulář, pokud se budeš držet mého postupu vygeneruješ v šabloně takto:
{form signInForm}
{*rozepsani formulare *}
{/form}
  1. Není potřeba v koncové značce {/form} psát název formuláře
  2. Aby si nemusel generovat prvky jeden po druhém, můžeš použít tuhle jednoduchou šablonu:
{form signInForm}
        <ul class="errors" n:if="$form->hasErrors()">
            <li n:foreach="$form->errors as $error">{!$error}</li>
        </ul>
    <table>
        {foreach $form->components as $component}
                {if $iterator->isLast()}
                    <tr>
                        <td colspan="2">Položky označené <span style="color:red;">*</span> jsou povinné.</td>
                    </tr>
                {/if}
            {if (!($component instanceof \Nette\Forms\Controls\HiddenField)) && (!($component instanceof \Nette\Forms\Controls\SubmitButton))}
                    <tr>
                        <th style="text-align: right;">{label $component->name /}:{if $component->isRequired()}<span style="color:red;">*</span>{/if}</th>
                        <td>{input $component->name}</td>
                    </tr>
            {/if}
            {if ($component instanceof \Nette\Forms\Controls\SubmitButton)}
                    <tr>
                        <td colspan="2" style="text-align: center">{input $component->name}</td>
                    </tr>
            {/if}
        {/foreach}
    </table>
{/form}

*) Poznámka: HiddenField se automaticky vykreslí před makrem {/form}

Editoval pilec (3. 3. 2012 18:31)

ZAJDAN
Člen | 45
+
0
-

díky
a co použít tento postup, který mi funguje ale zlobí mě, že se mi nedaří render poslat do příslušné šablony.
mám presenter:
app/presenters/RegistrationPresenter.php

use Nette\Forms\Form;
class RegistrationPresenter extends BasePresenter {

    public function renderDefault() {
        $this->template->setFile(__DIR__ . '/default.latte' );
        $this->template->render();

        /* $template->signInForm = $this->createComponentSignInForm(); */
        if ($this->context->parameters['productionMode'] === false) {
            $this->stubData();
        }
    }
    protected function createComponentForm() {
$form = new Form;
.....

a šablonu v templates/Registration/default.latte

{block #content}
<div class="bodyForm">
    {control form}
</div>
{/block}

problém je že render to vyrendruje pouze pokud je default.latte umístěno app/presenters/
jenže já chci aby render použil /templates/Registration/default.latte

Editoval ZAJDAN (3. 3. 2012 19:30)

Jan Endel
Člen | 1016
+
0
-

smaž řádek se setFile.

ZAJDAN
Člen | 45
+
0
-

pilec napsal(a):

smaž řádek se setFile.

tim jsem dostaval vystup:
Template file name was not specified
*15: $this->template->render(); *

ted mi pekne fachci jak jsi mi doporucil:

public function renderDefault() {
        $form->onSuccess[] = callback($this, 'FormSubmitted');

        if ($this->context->parameters['productionMode'] === false) {
            $this->stubData();
        }
    }
      protected function createComponentForm() {
    $form = new Form;

jen s tim rozdilem ze v sablone to vpustim:

{block #content}
<div class="bodyForm">
    {control form}
</div>
{/block}

a fachci to pekne

Editoval ZAJDAN (4. 3. 2012 1:27)

Jan Endel
Člen | 1016
+
0
-

to ti nemůže fungovat, řádek s:

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

musí být v metodě createComponent, poněvadž $form je proměnná lokální k té metodě.

a v presenteru v renderech nemusíš psát $this->template->render(); o to se stará Nette.

Editoval pilec (4. 3. 2012 2:04)

ZAJDAN
Člen | 45
+
0
-

zvláštní, pač to fungovalo i tak , ale máš pravdu…nějak jsem to přehlédl.
Nýní je to přesunuto kam to patří.
Teď bych měl otázku jakým způsobem ten formulář rozdělit na bloky tak abych každý blok měl v jiné třídě. Jde mi o stylování pomocí css.

Editoval ZAJDAN (4. 3. 2012 16:25)

ViPEr*CZ*
Člen | 814
+
0
-

To se nesmí form vykresilt takhle {control form}, ale musíš si udělat vlastní vykreslení.
https://doc.nette.org/cs/forms#…

ZAJDAN
Člen | 45
+
0
-

ViPErCZ napsal(a):

To se nesmí form vykresilt takhle {control form}, ale musíš si udělat vlastní vykreslení.
https://doc.nette.org/cs/forms#…

takže bych měl stávající callback:

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

nahradit za:

$form->render

?

ViPEr*CZ*
Člen | 814
+
0
-

Ne ne todle $form->onSuccess[] = callback($this, ‚FormSubmitted‘); je nejspíš na dobrým místě předpokládám a navíc jde o akci submittu… to nemá s css nic společného. Myslel jsem šablonu předělat.

ZAJDAN
Člen | 45
+
0
-

ViPErCZ napsal(a):

Ne ne todle $form->onSuccess[] = callback($this, ‚FormSubmitted‘); je nejspíš na dobrým místě předpokládám a navíc jde o akci submittu… to nemá s css nic společného. Myslel jsem šablonu předělat.

někde se přece musí říct, že se bude renderovat manuálně a to tedy řeší jen změna zápisu v latte?
z {control Form} na {form Form} ?

ViPEr*CZ*
Člen | 814
+
0
-

Jo, prostuduj si tu dokumentaci co jsem poslal link… tam to je hezky ukázané. Každopádně pokud chceš stylovat, dá se použít i to co máš. Každý element má svoje IDéčko, takže to jde ostylovat i tak jednoduše.

ZAJDAN
Člen | 45
+
0
-

ViPErCZ napsal(a):

Jo, prostuduj si tu dokumentaci co jsem poslal link… tam to je hezky ukázané. Každopádně pokud chceš stylovat, dá se použít i to co máš. Každý element má svoje IDéčko, takže to jde ostylovat i tak jednoduše.

mě jde spíše o to, aby se formulář zavřel do jednoho generálního divu, což řeším v latte šabloně. Ale uvnitře tohodle divu udělat ještě další divy a do ni vpouštět jednolivé bloky formuláře. Tím bych pak mohl jednotlivým divům nastavit různé pozadí atd.

ViPEr*CZ*
Člen | 814
+
0
-

ZAJDAN napsal(a):

ViPErCZ napsal(a):

Jo, prostuduj si tu dokumentaci co jsem poslal link… tam to je hezky ukázané. Každopádně pokud chceš stylovat, dá se použít i to co máš. Každý element má svoje IDéčko, takže to jde ostylovat i tak jednoduše.

mě jde spíše o to, aby se formulář zavřel do jednoho generálního divu, což řeším v latte šabloně. Ale uvnitře tohodle divu udělat ještě další divy a do ni vpouštět jednolivé bloky formuláře. Tím bych pak mohl jednotlivým divům nastavit různé pozadí atd.

Jasný pak viz. dokumentace.

{form form}
{control $form errors}
<div id="mujdiv">{form['jmeno']->label}{form['jmeno']->control}</div>
{/form form}
ZAJDAN
Člen | 45
+
0
-

neni mi ulne jasne zda toto makro:
{form form}
se nazvem odkazuje na nazev promene nebo nazev komponenty?

ViPEr*CZ*
Člen | 814
+
0
-

První form je tuším název makra a druhý form je název komponenty. Tj. mohlo by tam místo toho být např.:
{form loginForm}

ZAJDAN
Člen | 45
+
0
-

ViPErCZ napsal(a):

První form je tuším název makra a druhý form je název komponenty. Tj. mohlo by tam místo toho být např.:
{form loginForm}

vypadá to, že je tomu tak {form nazevKomponenty}
ovšem v mém případě to komponentu s použitím tohoto makra hledá jinde než bych chtěl a nemůže ji najít
dostávám výstup:
Component with name ‚RegForm‘ does not exist.
já tu komponentu vytvářím v presenteru /presenters/RegistrationPresenter

protected function createComponentRegForm() {
    $form = new Form;
.........
ViPEr*CZ*
Člen | 814
+
0
-

A máš tam {form regForm} ???

ZAJDAN
Člen | 45
+
0
-

ViPErCZ napsal(a):

A máš tam {form regForm} ???

samozřejmě…tak jak se jmenuje komponenta tak ji volam v makru, ale abych pravdu řekl mám tam:
{form RegForm}

Editoval ZAJDAN (4. 3. 2012 18:45)

ZAJDAN
Člen | 45
+
0
-

tak po pár změnách jsem dosáhl žádaného vysledku:
latte vypadá takto (zatím):

{block #content}
{form regForm}
<div class="bodyForm">
    {control regForm}
    <div id="Form1">{$form['name']->label}{$form['name']->control}</div>
</div>
<div class="fotoContainer">
 <div id="Form2">{$form['avatar']->label}{$form['avatar']->control}</div>
</div>
{/form regForm}
{/block}

Editoval ZAJDAN (5. 3. 2012 0:42)

ViPEr*CZ*
Člen | 814
+
0
-

Třída Form umí kontejnerovat: https://doc.nette.org/cs/forms#…
Dále {control regForm} v tom bloku bude nějaký divoký. A id=„Form1“ je tam 2×, což není také dobře.

ZAJDAN
Člen | 45
+
0
-

ViPErCZ napsal(a):

Třída Form umí kontejnerovat: https://doc.nette.org/cs/forms#…
Dále {control regForm} v tom bloku bude nějaký divoký. A id=„Form1“ je tam 2×, což není také dobře.

jasně to dvojí ID vím… to bylo ihned po nakopírování -ale to je samozřejmost…i tak díky

a to seskupování – grupování to je přesně ono to se mi líbí…díky
co by mě ale zajímalo jak se v šabloně odkážu na konkrétní Group

Editoval ZAJDAN (4. 3. 2012 21:12)

Jan Endel
Člen | 1016
+
0
-
{formGroup 'skupina'}
	{input inputVeSkupine}
{/formGroup}

nebo

{input skupina-inputVeSkupine}
ZAJDAN
Člen | 45
+
0
-

zkouším to ale dostanu:
Unknown macro {formGroup} in …/Registration/default.latte
předpokládám, že takové makro budu muset nadefnovat někde do seznamu maker

Editoval ZAJDAN (4. 3. 2012 23:11)