Closed gremo closed 1 month ago
As stated in the documentation, emit()
only accept some scalars in the array, so you won't be able to pass "new Notification()" like that (at least not a specific instance)
You can also pass extra (scalar) data to the listeners
So i see two potential options (there may be more):
Last "option" / "alternative": if you dispatch this Event from PHP, and only listen to it in another PHP class... you could also use a standard EventDispatcher and avoid a maybe-unwanted roundtrip via the front-end (not sure if applicable in your case, but sometimes it can be a good idea)
@smnandre thanks for the idea. Do the hydrateWith / dehydrateWith process occurs also when using #[LiveArg]
? For what I understand from the docs, it seems that the process is used only when passing props to the component....
There may be a better way, but i tried something and i believe it suits your needs :
Twig Component
#[AsLiveComponent('Foo')]
class Foo extends AbstractController
{
use DefaultActionTrait;
use ComponentToolsTrait;
#[LiveAction]
public function bar(): void
{
$this->emit('FooBar', ['notification' => new Notification('Hello', 'World!')]);
}
#[LiveListener('FooBar')]
public function onFooBar(
#[LiveArg('notification')] #[ValueResolver(NotificationResolver::class)] Notification $notification
)
{
dump($notification);
}
}
Twig Template
<div {{ attributes.defaults({}) }}>
<button
type="button"
data-action="live#action"
data-action-name="bar()"
>BAR</button>
</div>
Notification DTO
class Notification
{
public function __construct(
public string $title,
public string $message,
) {
}
public function getTitle(): string
{
return $this->title;
}
public function getMessage(): string
{
return $this->message;
}
}
And a little ValueResolver
class NotificationResolver implements ValueResolverInterface
{
public function resolve(Request $request, ArgumentMetadata $argument): array
{
if (Notification::class !== $argument->getType()) {
return [];
}
if (!is_array($attribute = $request->attributes->get($argument->getName()))) {
return [];
}
if (!isset($attribute['title']) || !isset($attribute['message'])) {
return [];
}
if (!is_string($attribute['title']) || !is_string($attribute['message'])) {
throw new NotFoundHttpException(sprintf('The notification for the "%s" parameter is invalid.', $argument->getName()));
}
return [new Notification($attribute['title'], $attribute['message'])];
}
}
And when you click on the button, the live action is called, the event is emitted, and you can get the notification object as you wanted.
Requests | Debug |
---|---|
Thank you for this issue. There has not been a lot of activity here for a while. Has this been resolved?
I've a
Notifier
component which is listening to the "show" event and accept aNotification
object:Right now, when I try to emit the event, an error occurred:
... because argoment is "translated" (serialized I assume) as an
array
.In the docs the example works because
Product
is an entity, and the param converter system kicks in, transforming theint
passed toemit
back to anobject
.How to obtain the same result in my example?