Jak na snipet uvnitř formulářového makra

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

Snažím se udělat formulář, jehož jedna část by se překreslovala snipetem. Na foru jsem našel několik návodů, ale v současné verzi mi bohužel nefungují.

Našel jsem toto (což nefunguje, protože proměnná $_form byla odebrána):

{form newForm}
    ...
    {snippet foo}
        {var $_form = $control['newForm']}
        a uz to bude fungovat
    {/snippet}
{/form}

Zkoušel jsem upravit na:

{var $form = $control['newForm']}

Zde ale při pokusu o překreslení snipetu, vyskočí chyba: end() expects parameter 1 to be array, null given

Cílem je formulář, který se skládá ze tří částí:

  1. fomulářové prvky pro zadání adresy
  2. radio list kde je seznam nabízených přeprav
  3. radio list kde je seznam nabízených plateb (tuto část právě potřebuji překreslovat snipetem, vždy když se změní radio list se seznamem nabízených přeprav. To řeším js skriptem:
$.nette.ajax({
	url: {link invalidate!},
    data: {
    	'value': $('input[name=shipping]:checked').val()
        	}
     });

Vše mi funguje až na to překreslení části formuláře snipetem.
Dokázal by mi někdo poradit, jak překreslovat jen jednu část formuláře ? Díky za každou radu.

Mysteria
Člen | 797
+
0
-

V novém Nette se to dělá takto: https://forum.nette.org/…nette-2-4-rc#…

andros
Člen | 145
+
0
-

Mysteria napsal(a):

V novém Nette se to dělá takto: https://forum.nette.org/…nette-2-4-rc#…

Mohl bys mi dát nějaký konkrétní příklad prosím ?

Mysteria
Člen | 797
+
0
-

Stačí takhle?

// Presenter
if ($this->presenter->ajax) $this->template->getLatte()->addProvider('formsStack', [$this['search']]);
<!-- Šablona -->
<form n:name='search' class='ajax search'>
	<div n:snippet='search'>
		<input n:name='search' />
		<input n:name='order' />
	</div>
</form>
andros
Člen | 145
+
0
-

To jsem zkoušel, do presenteru v metodě renderDefault jsem dal

$this->template->getLatte()->addProvider('formsStack', [$this['orderForm']]);

a část formu jsem obalil snipetem.

Pořád ale dostávám chybovou hlášku: Undefined variable: form

Marek Bartoš
Nette Blogger | 1177
+
0
-

form, newForm, orderForm… nepoužíváš v šabloně jiný název, než jsi použil při definování komponenty?

andros
Člen | 145
+
0
-

v presenteru mám formulářovou továrničku

protected function createComponentOrderForm()
    {
		$form = new Form();
		...
	}
Mysteria
Člen | 797
+
0
-

Já mám ten kód v metodě beforeRender, možná je už v render metodě pozdě, tak to zkus přesunout do action metody. Pokud to nebude fungovat ani tak, tak sem hoď i kód šablony.

andros
Člen | 145
+
0
-

Zkoušel jsem ho dát všude (renderDefaul, ActionDefault, i BeforeRender) a výsledek je pořád stejný: Undefined variable: form

Celé to mám takto:

public function beforeRender()
    {
        parent::beforeRender();
        $this->template->getLatte()->addProvider('formsStack', [$this['orderForm']]);
    }

Tady se IDE nelíbí že metoda getLatte() není ve třídě \stdClass

Továrnička formuláře:

protected function createComponentOrderForm()
    {

        $form = new Form();

        $form->addTextArea('note','Poznámka k objednávce', NULL, 5)
            ->setAttribute('class','form-control');

        $delivery = $this->deliveryManager->getDeliveryUsers()->fetchPairs('id','name');
        if ($this->deliveryId === null) {

            $delivery_default = $this->deliveryManager->getDeliveryUsersDefault();
        }
        else {

            $delivery_default = $this->deliveryId;
        }

        $form->addRadioList('shipping', NULL, $delivery)->setDefaultValue($delivery_default);

        $payments = $this->paymentManager->getPaymentsByDeliveryId($delivery_default)->fetchPairs('id','name');
        $form->addRadioList('payments',NULL, $payments)->setDefaultValue(key($payments));

        $form->addSubmit('send', 'Odeslat objednávku')
            ->setAttribute('class','btn btn-primary');

        $form->onSuccess[] = [$this, 'postFormSucceeded'];

        return $form;
    }

Handle metoda volaná Ajaxem, při změně první části formu

public function handleInvalidate($value)
    {
        $this->deliveryId = $value;
        $this->branch = $this->deliveryManager->DeliveryBranchById($value);

        $this->redrawControl('payments');
        bdump($value);
    }

A v latte mám formulář:

{form orderForm}
                <div class="col-md-4">
                    <div class="form-col">
                        <h3>Vyberte dopravu</h3>
                        <div class="ship-list">
                            {foreach $form[shipping]->items as $key => $label}
                                <div class="radio">
                                    <label n:name="shipping:$key"><input n:name="shipping:$key"> {$label} <span class="text-primary">zdarma</span></label>
                                </div>
                            {/foreach}
                        </div>

                        <div class="form-group mb-lg">
                            <h3>Poznámka k objednávce <a class="expand-plus collapsed" role="button" data-toggle="collapse" href="#noteOrder" aria-expanded="false" aria-controls="noteOrder"></a></h3>

                            <div class="collapse" id="noteOrder">
                                <div class="form-group wide">
                                    {input note}
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="col-md-4">
                    <div class="form-col">
                        <h3>Vyberte platbu</h3>
						{snippet payments}
                        <div class="checkout-payment-method">
                            {foreach $form[payments]->items as $key => $label}
                                <div class="radio">
                                    <label n:name="payments:$key"><input n:name="payments:$key"> {$label}</label>
                                </div>
                            {/foreach}
                        </div>
						{/snippet}
                        <div class="checkout-review-action">
                            {input send}
                        </div>
                    </div>
                </div>
                {/form}

Nakonec je ve stejnném latte taky js script, který zavolá handle metodu , při změně v radio listu

<script>
    $('body').on('change','input[name=shipping]:radio',function(){
        $.nette.ajax({
            url: {link invalidate!},
            data: {
                'value': $('input[name=shipping]:checked').val()
            }
        });
    });
</script>

Editoval andros (16. 2. 2017 10:30)

Marek Bartoš
Nette Blogger | 1177
+
0
-

Kde ti to tu chybu vyhazuje?
Bez manuálního renderu to funguje nebo ne?

andros
Člen | 145
+
0
-

Chybu to začne vyhazovat jakmile část formuláře, který potřebuju překreslit, obalím snippetem {snippet payments} {/snippets}, takže když tyhle obalovací značky smažu, vše funguje (až na to překreslení při změně ve formuláři)

filsedla
Člen | 101
+
0
-

Přesně se stejným problémem jsem se taky setkal. Nešel udělat snippet uvnitř formuláře a následně uvnitř snippetu např. manuálně vykreslit radio list (je k tomu potřeba $form). Správné řešení jsem neobjevil.

Mortisson
Člen | 21
+
+1
-

Správné řešení je takhle:

<?php
	{form newForm}
    	...
    	{snippet foo}
        	{var $form = $control['newForm']}
        	{input $form->getComponent('nazevInputu')}
    	{/snippet}
	{/form}
?>

V tom snippetu se pak už musíš odkazovat přímo na tu proměnou $form

andros
Člen | 145
+
0
-

Díky moc, teď už to funguje jak potřebuji.

andros
Člen | 145
+
0
-

věděl by někdo jak se zbavit chybové hlášky v IDE PhpStorm „Method ‚getLatte‘ not found in \stdClass“ u:

$this->template->getLatte()->addProvider('formsStack', [$this['orderForm']]);
andros
Člen | 145
+
0
-

věděl by někdo jak se zbavit chybové hlášky v IDE PhpStorm „Method ‚getLatte‘ not found in \stdClass“ u:

$this->template->getLatte()->addProvider('formsStack', [$this['orderForm']]);