contributte/event-dispatcher v komponentě
- lookass
- Člen | 54
Ahoj, chtěl bych poradit, co dělám špatně, popř. jak zprovoznit
contributte/event-dispatcher v komponentě.
V presenteru mi všechno funguje jak má, ale v komponentě nikoliv.
Mám komponentu:
class UserDetail extends \Nette\Application\UI\Control implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
testEvent::class => 'test'
];
}
public function test(): void
{
$this->redrawControl('test');
}
}
Nějaký model:
class Model
{
public function __construct(private \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $eventDispatcher)
{
}
public function someMethod()
{
$this->eventDispatcher->dispatch(new testEvent(new stdClass()));
}
}
V momentě, kdy z jiné komponenty zavolám metodu
someMethod()
z třídy Model, nedojde k předání toho eventu do
UserDetail.
Nechápu, proč mi to v presenteru funguje a v kopmonentě nikoliv. Něco
zapomínám registrovat do configu?
config:
extensions:
events: Contributte\EventDispatcher\DI\EventDispatcherExtension
Děkuji předem za případnou pomoc!
Editoval lookass (2. 3. 2021 14:34)
- David Matějka
- Moderator | 6445
Ahoj, komponenty maji dva problémy, proč to nefunguje:
- nejsou v DI containeru jako services
- jsou lazy
Pokud si ale vytvoříš na komponentu factory, tak by mělo jít nastavit setup, který ji přidá jako subscriber. V DI extension zhruba takto:
$builder->addFactoryDefinition($this->prefix('userDetail'))
->setImplement(App\UserDetailFactory::class)
->getResultDefinition()
->addSetup('$this->getService(?)->?(?)', ['events.dispatcher', 'addSubscriber', '@self']);
A za druhé musíš tu komponentu v presenteru inicializovat brzo (rozuměj před tím, než se vyvolá event), takže třeba v startup/action
$this['userDetail']
- lookass
- Člen | 54
@DavidMatějka Asi teda bude lepší komponentu jako EventSubscriber nepoužívat, ale vytvořit další třídu např. UserDetailEventsSubscrieber, tu dát jako servisu do DI, a potom jí pouze předat parametrem instanci té komponenty.
Subscrieber by tedy mohl vypadat takto:
class TestEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
TestEvent::class => 'test'
];
}
public function test(TestEvent $event)
{
$event->call();
}
}
Event:
class TestEvent
{
public function __construct(private object $object)
{
}
public function call()
{
$class = $this->object;
$class->someMethod();
}
}
A potom můžu v komponentě v handleru zavolat metodu z modelu:
public function handleTest(): void
{
$model->doSomething($this);
}
A modelu předat instanci komponenty do Eventu
public function doSomething($control)
{
//do something ...
//create event
$this->eventDispatcher->dispatch(new TestEvent($control);
}
Tohle funguje, ale nevím, zda to je správné takhle používat.