Komponenta a tovární metoda

martinkobelka
Člen | 4
+
0
-

Zkouším si podle dokumentace vytvořit komponentu za pomocí tovární metody. Problém je ale v tom, že v dokumentaci je uvedeno, že podle následujícího rozhraní by měla být při vytváření zavolána metoda create() Mám tedy následující tovární metodu a k ní komponentu.

namespace App\Components;

use Nette\Application\UI;


interface ICategoryFormFactory
{
    /**
     * @return CategoryForm
     */
    public function create();
}

class CategoryForm extends Nette\Object
{

    public function create()
    {
        $form = new UI\Form;
        // mohu použít $this->database

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

        return $form;
    }
}

Mě se ale při zavolání zavolá __construct() a metoda create zůstává mrtvá. Mohl by mi s tím prosím někdo poradit?

Takto se potom snažím vytvořit komponentu v prezenteru

	/**
	 * Vytvoří komponentu formuláře
	 */
	protected function createComponentLoginForm(){

		return $this->CategoryFormFactory->create();
	}

Editoval martinkobelka (9. 6. 2017 10:33)

David Matějka
Moderator | 6445
+
+2
-

Ahoj, tvoje „CategoryForm“ je ve skutecnosti uz sama o sobe tovarna na formular/komponentu. takze by se to melo jmenovat CategoryFormFactory a registrujes to jako sluzbu. (a vubec nebude existovat ICategoryFormFactory)

Ty tovarny na komponenty pres rozhrani slouzeji k tomu, kdyz si vytvoris komponentu (tridu, ktera dedi od UI\Control).

v tomhle pripade by to tedy vypadalo treba:

interface ICategoryFormFactory
{
    /**
     * @return CategoryForm
     */
    public function create();
}

class CategoryForm extends UI\Control
{

    protected function createComponentForm()
    {
        $form = new UI\Form;
        // mohu použít $this->database

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

        return $form;
    }
}

pak budes tedy v presenteru vytvaret pres to rozhrani tuhle komponentu a ta ma v sobe dalsi komponentu se samotnym formularem.

martinkobelka
Člen | 4
+
0
-

David Matějka napsal(a):

Ahoj, tvoje „CategoryForm“ je ve skutecnosti uz sama o sobe tovarna na formular/komponentu. takze by se to melo jmenovat CategoryFormFactory a registrujes to jako sluzbu. (a vubec nebude existovat ICategoryFormFactory)

Ty tovarny na komponenty pres rozhrani slouzeji k tomu, kdyz si vytvoris komponentu (tridu, ktera dedi od UI\Control).

v tomhle pripade by to tedy vypadalo treba:

interface ICategoryFormFactory
{
    /**
     * @return CategoryForm
     */
    public function create();
}

class CategoryForm extends UI\Control
{

    protected function createComponentForm()
    {
        $form = new UI\Form;
        // mohu použít $this->database

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

        return $form;
    }
}

pak budes tedy v presenteru vytvaret pres to rozhrani tuhle komponentu a ta ma v sobe dalsi komponentu se samotnym formularem.

Však v presenteru vytvářím přes toto rozhraní.

	/**
	 * @var ILoginFormComponentFactory
	 * @inject
	*/
	public $loginFormFactory;

	/**
	 * Vytvoří komponentu formuláře
	 */
	protected function createComponentLoginForm(){

	return $this->CategoryFormFactory->create();
	}

Ale to řádek v createComponentLoginForm() mi zavolá konstruktor a ne metodu create. Funguje mi to jen takto.

/**
	 * Vytvoří komponentu formuláře
	 */
	protected function createComponentLoginForm(){

		$form =  $this->loginFormFactory->create();
		return $form->createComponentLoginForm();
	}

Editoval martinkobelka (9. 6. 2017 14:14)

David Matějka
Moderator | 6445
+
0
-

ale ta tva trida CategoryForm neni komponenta, ale tovarna. takze ty pomoci ICategoryFormFactory vytvoris instanci te CategoryForm.

jak jsem psal – pokud v te tride mit pouze definici formulare, tak to rozhrani nemusis pouzivat, jen registrujes CategoryForm jako sluzbu (respektive prejmenovane na CategoryFormFactory) a budes to vytvaret primo pomoci teto sluzby

pokud chces vytvorit komponentu, ktera v sobe ma dalsi formular, tak viz ten muj prispevek. jeste mrkni na https://doc.nette.org/…s/form-reuse

martinkobelka
Člen | 4
+
0
-

David Matějka napsal(a):

ale ta tva trida CategoryForm neni komponenta, ale tovarna. takze ty pomoci ICategoryFormFactory vytvoris instanci te CategoryForm.

jak jsem psal – pokud v te tride mit pouze definici formulare, tak to rozhrani nemusis pouzivat, jen registrujes CategoryForm jako sluzbu (respektive prejmenovane na CategoryFormFactory) a budes to vytvaret primo pomoci teto sluzby

pokud chces vytvorit komponentu, ktera v sobe ma dalsi formular, tak viz ten muj prispevek. jeste mrkni na https://doc.nette.org/…s/form-reuse

Když vytvožím komponentu přesně podle tvého příspěvku, tak se mi zavolá při ale metoda __construct a ne create

Můj kod komponenty

<?php

namespace App\components;

use Nette\Application\UI\Control as Control;
use Nette\Application\UI\Form;


interface ILoginFormComponentFactory
{
    /**
     * @return LoginFormComponent
     */
    public function create();
}

class LoginFormComponent extends Control {


	public function createComponentLoginForm() {

		$form = new Form;
		 // Získáme existující operace kalkulačky a dáme je do výběru operací.

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

	}
}

Můj kod prenezenteru

/**
	 * @var ILoginFormComponentFactory
	 * @inject
	*/
	public $loginFormFactory;

	/**
	 * Vytvoří komponentu formuláře
	 */
	protected function createComponentLoginForm(){

		return $this->loginFormFactory->create();
	}

Výsledek

Nette\MemberAccessException
Call to undefined method App\components\LoginFormComponent::render()

Ovšem v tutoriálu https://doc.nette.org/…s/form-reuse metoda render vůbec není.

Metoda create kterou implementuje nette vůbec nezavolá metodu create z mé komponenty. ale __construct(). To je to na co se celou dobu ptám proč. V tutoriálu je napsáno, že vygenerovaná metoda create zavolá metodu create z mého kontroleru

Editoval martinkobelka (9. 6. 2017 16:54)

CZechBoY
Člen | 3608
+
0
-

Tak co vlastne chces?
Pouzivat generovany tovarny pres interface?
Vlastni tovarnu?
Formular v komponente s vlastni sablonou?
Svoji tovarnu implementujici interface?

David Matějka
Moderator | 6445
+
+2
-

Když vytvožím komponentu přesně podle tvého příspěvku, tak se mi zavolá při ale metoda __construct a ne create

ano, to je spravne chovani. generovane tovarny vytvareji instance trid. nevolaji tvoji metodu

Ovšem v tutoriálu .. metoda render vůbec není.

j, to je bohuzel pravda. nejsnazsi render pro formular muze vypadat nasledovne:

public function render()
{
	$this['form']->render();
}

V tutoriálu je napsáno, že vygenerovaná metoda create zavolá metodu create z mého kontroleru

kde to je napsany, ze to zavola tvoji metodu create?

martinkobelka
Člen | 4
+
0
-

David Matějka napsal(a):

Když vytvožím komponentu přesně podle tvého příspěvku, tak se mi zavolá při ale metoda __construct a ne create

ano, to je spravne chovani. generovane tovarny vytvareji instance trid. nevolaji tvoji metodu

Ovšem v tutoriálu .. metoda render vůbec není.

j, to je bohuzel pravda. nejsnazsi render pro formular muze vypadat nasledovne:

public function render()
{
	$this['form']->render();
}

V tutoriálu je napsáno, že vygenerovaná metoda create zavolá metodu create z mého kontroleru

kde to je napsany, ze to zavola tvoji metodu create?

Díky tím jsi mi vše vyjasnil :)