Komponenta vytvářená továrničkou nevrací instaci komponenty

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

Ahoj,
mám chybovou hlášku:

Nette\UnexpectedValueException

Method FrontendModule\PagesPresenter::createComponentBox() did not return or create the desired component.

Vím co to znamená, ale nevím jak to opravit. S neonem zatím nejsem nejlepší kamarád.
Když vytvářím komponentu konstruktorem, tak to jde:

public function createComponentBox()
{
	return new \Box($this->pageModel);
}

Když ji ale chci vytvořit továrničkou, tak to nejde. Postupoval jsem (doufám) přesně podle Vícenásobné použití formuláře: dědičnost nebo továrna?, ale hází mi to tu chybu.

presenter:

	public $box;

public function __construct(\Box $box)
{
		$this->box = $box;
}

public function createComponentBox()
{
		return $this->box->action();
}

neon:

services:
	box: Box

Box:

use Nette\Application\UI\Control;
class Box extends Control
{

	private $db;
	private $box;

	public function __construct(Nette\Database\Connection $db)
	{
		$this->db = $db;
	}

	public function action()
	{
		$this->box = 'ahoj';
	}

	public function render()
	{
		$this->template->box = $this->box;
		$this->template->setFile(dirname(__FILE__) . '/template.latte');
		$this->template->render();
	}

}

Otázka teda zní, proč to nevytváří komponentu?
Díky

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Protože v té továrničce vracíš výsledek metody action(), což je řetězec 'ahoj'. Vracej pouze tu komponentu.

Oli
Člen | 1215
+
0
-

Jaj, to mě vubec nenapadlo, že tam musím tu komponentu vrátit :-) Díky!

David Matějka
Moderator | 6445
+
0
-

jinak, to pouziti neni spravne. komponenta by nemela byt registrovana jako sluzba, mel bys mit registrovanou pouze tovarnu na komponentu, s DI factories se to zjednodusuje, bez nich je to o par radku slozitejsi, ale fakt jen o par :)

1. pri obojim budes mit componentu jako mas ted:

class Box extends Control
{

	public function __construct(NejakaZavislost $foo)
	{
	....
	}
	...
}

2a. pokud pouzijes DI factories , tak napises tohle interface

interface BoxFactory
{
	public function create();
}

a do configu:

factories:
	boxFactory:
		class: Box
		implement: BoxFactory

2b. pokud nepouzijes DI factories, tak musis tovarnu napsat rucne

class BoxFactory extends Nette\Object
{
	protected $foo;

	public function __construct(NejakaZavislost $foo)
	{
		$this->foo = $foo;
	}

	public function create()
	{
		return new Box($this->foo);
	}
}

a registrujes tovarnu jako sluzbu:

services:
	boxFactory: BoxFactory

3. pouziti v presenteru je pak stejne

class BarPresenter extends BasePresenter
{
	protected $boxFactory;

	public function __construct(BoxFactory $boxFactory)
	{
		$this->boxFactory = $boxFactory;
	}

	public function createComponentBox()
	{
		return $this->boxFactory->create();
	}

}

factory muzes samozrejme injectnout i pres inject* metody, @autowire nebo nejlepe injectnutim primo do createComponent* metody

takhle muzes pouzit „Box“ ve více komponentách (respektive createComponent* metodach), v tvem reseni by to byla vsude stejna instance…