Komponenta při prekreslení snippetu se nedokáže vykreslit

Danny
Člen | 146
+
0
-

zdravím,
potřeboval bych poradit. Mám vytvořenou komponentu kde mám multiplier

	public function createComponentForm() {

		return new UI\Multiplier(function() {
			$form = new UI\Form;
			$form->setTranslator($this->translator);
			$form->getElementPrototype()->addAttributes(array('class' => 'ajax'));

			$form->addHidden('type', $this->type);
			$form->addText('name', 'messages.layout.form.name')
				->setRequired('Zadejte jméno');

			$form->addEmail('email', 'messages.layout.form.email')
				->setRequired('Zadejte email');

			$form->addTextArea('content', 'messages.layout.form.content')
				->setRequired('Zadejte dotaz');

			$form->addSubmit('send', 'messages.layout.form.send');

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

			return $form;
		});
	}

V render metode komponenty predavam ID do sablony

{control multipleForm, $id}
	public function render($id)
	{
		$template = $this->template;
		$template->setTranslator($this->translator);
		$template->id= $id;
		$template->setFile(__DIR__ . '/component.latte');
		$template->render();
	}

a vykresluju podle toho multipler form

component.latte

{snippet formSnippet}
<div class="contact-box">
    {form form-$id}
    <div class="contact-form">
        <div>
            <div class="form-group">
                {label email/}
                {input email}
            </div>
        </div>
        <div>
            <div class="form-group textarea">
                {label content/}
                {input content}
            </div>

        </div>
    </div>
    {/form}
</div>
{/snippet}

Vše funguje bez problému ale pokud tu componentu při zpracování(odeslání) zpracuju ajaxem a refresnu snippet snippetForm tak mi to hodí hlášku
Nette\InvalidArgumentException Component name must be non-empty alphanumeric string, '' given.
Arguments: form-

Pochopil jsem to tak že při překreslení snippet ten form nezná ID a proto není schopný vykreslit form- místo např form-1.

Věděl by někdo jak tohle vyřešit?
Díky moc :)

David Matějka
Moderator | 6445
+
0
-

trochu se ztracim v hierarchii (kdej je to multipleForm definovany?) komponent, ale problem bude asi v {control multipleForm, $id}. nikdy nepredavej data do render metody komponenty, s ajaxem to nefunguje. predavej to primo v createComponent* metode. pokud vykreslujes vice komponent, tak pouzij multiplier.

a to tve pouziti multiplieru je divny, predavas tam id pres {control form-$id}, ale nikde ho nezpracovavas, jelikoz tam mas jen

return new UI\Multiplier(function() {

a dle component.latte to vypada, ze tam vykreslujes vzdy jen jeden formular

nebude ti uplne stacit, kdyz budes mit komponentu s formularem:

public function createComponentForm() {
        $form = new UI\Form;
        $form->setTranslator($this->translator);
        $form->getElementPrototype()->addAttributes(array('class' => 'ajax'));

        $form->addHidden('type', $this->type);
        $form->addText('name', 'messages.layout.form.name')
            ->setRequired('Zadejte jméno');

        $form->addEmail('email', 'messages.layout.form.email')
            ->setRequired('Zadejte email');

        $form->addTextArea('content', 'messages.layout.form.content')
            ->setRequired('Zadejte dotaz');

        $form->addSubmit('send', 'messages.layout.form.send');

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

        return $form;
}

bez multiplieru a z presenteru rovnou predavat ID v createComponent* metode?


vice o fungovani snippetu v https://www.youtube.com/watch?…

Danny
Člen | 146
+
0
-

Díky za reakci.

Princip je takový že sem chtěl vytvořit komponentu kterou budu moct použít víckrát v projektu, respektive potřebuju formulář který může být buď poptávka/nabídka/dotaz. Položky budou pořád stejné, jen se bude lišit IDčkem.

Form pro poptávku a nabídku je ve footeru takže jí injectuju rovnou v base presentru aby se includovala vždy v šablone, na každé stránce.

V base presentru teda mám:

	public function createComponentMultipleForm () {
		return $this->contactComponent->build();
	}

A pak ve footeru mám (momentálně místo ID předávám konstantu OFFER atd)

{control multipleForm, 1}
{control multipleForm, 2}

Šlo mi o to že bych si jenom v šablone předal parametr do komponenty a v komponentě vykreslil ten form s tímto ID, nebo s jiným příznakem.

David Matějka
Moderator | 6445
+
0
-

ok, udelej to zhruba nasledovne:

public function createComponentMultipleForm () {
	return new Multiplier(function ($id) {
	    return $this->contactComponent->build($id);
	});
}

a to contactComponent->build($id) ti vrati komponentu, ktere preda id nekam do konstruktoru a ta uz pod sebou nemusi mit zadny mutliplier, v createComponentForm bude vracet klasicky form

a ve footer pak budes zapisovat {control multipleForm-1}

Danny
Člen | 146
+
0
-

Když to udělám takto, tak mi to píše

Nette\MemberAccessException
Call to undefined method Nette\Application\UI\Multiplier::render().

Předpokládám že je to ta metoda Render kterou mám v komponentě, v které si setuju template atd, ale nechápu proč jí to nezná.

public function render($id)
{
    $template = $this->template;
    $template->setTranslator($this->translator);
    $template->id= $id;
    $template->setFile(__DIR__ . '/component.latte');
    $template->render();
}
David Matějka
Moderator | 6445
+
0
-

opravdu mas v sablone {control multipleForm-1} a ne {control multipleForm 1}?

Danny
Člen | 146
+
0
-

Jo promiň máš pravdu, upravil jsem to a mám

{control multipleForm-1}
{control multipleForm-2}

ale pak se dostanu do bodu kdy mi to píše
Component ‚1‘ already has a parent

David Matějka
Moderator | 6445
+
0
-

$this->contactComponent->build($id); musi vzdy vracet novou instanci komponenty

Danny
Člen | 146
+
0
-

Tak jsem to upravil aby build($id) vracel vždycky novou instanci, ale teď teda nevím jak tam zase zakomponovat to aby ta komponenta používala vlastní template tu component.latte pro vykreslení, protože takhle ten

{control multipleForm-1}

mi vykreslí sám ten formulář.

Danny
Člen | 146
+
0
-

Takhle vypadá ta komponenta

<?php

namespace App\FrontendModule\Components;

class ContactComponent extends BaseControl
{

	//constructor a zavislosti atd..

	public function build($id) {

		$form = new UI\Form;
		$form->setTranslator($this->translator);
		$form->getElementPrototype()->addAttributes(array('class' => 'ajax'));

		// inputs...

		$form->addSubmit('send', 'messages.layout.form.send');

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

		return $form;
	}

	public function contactFormSucceeded(UI\Form $form, $values) {

		//zpracovani

	}

	public function render()
	{
    	$template = $this->template;
    	$template->setTranslator($this->translator);
    	$template->setFile(__DIR__ . '/component.latte');
    	$template->render();
	}
}

Editoval Danny (30. 8. 2018 10:53)

David Matějka
Moderator | 6445
+
+1
-

jsem myslel, ze build je nejaka tovarna, ktera ti bude vytvaret tu komponentu ContactComponent, ale ono ti to vraci ten formular. mrkni "do dokumentace':https://doc.nette.org/…n/components#… jak psat komponenty s tovarnama.

Danny
Člen | 146
+
0
-

Díky za nakopnutí a za pomoc Davide :-)