Open JanMikes opened 2 years ago
Thank you for this issue. There has not been a lot of activity here for a while. Has this been resolved?
Hi, afaik this issue (feature request) is still valid.
This is normal because the stimulus controller does not allow you to add several topics: https://github.com/symfony/ux/blob/416753fcdcd0c9b4a88b613239eeefe32583f8d9/src/Turbo/assets/src/turbo_stream_controller.ts#L36
It would then be necessary to modify the stimulus controller to be able to loop over several topics.
And
must become
topics: Array,
But could you add several controllers ? (and that would be safer i guess)
@smnandre How so ? I don't understand.
@seb-jean i guess the idea is that twig function renderTurboStreamListen(Environment $env, $topic)
would accept string|array and based on that would put into template different stimulus controller -> one with support for single topic, the other for multiple.
Why not!
@JanMikes do you think you can create a PR?
I looked on the Mercure site and you have to do this to add multiple topics at once:
// The subscriber subscribes to updates
// for the https://example.com/foo topic, the bar topic,
// and to any topic matching https://example.com/books/{name}
const url = new URL('https://example.com/.well-known/mercure');
url.searchParams.append('topic', 'https://example.com/foo');
url.searchParams.append('topic', 'bar');
url.searchParams.append('topic', 'https://example.com/bar/{id}');
const eventSource = new EventSource(url);
// The callback will be called every time an update is published
eventSource.onmessage = function ({data}) {
console.log(data);
};
Source: https://mercure.rocks/spec#subscription
Which means that we could then loop on the following line to add several topics: https://github.com/symfony/ux/blob/2.x/src/Turbo/assets/src/turbo_stream_controller.ts#L36C9-L36C57
When do you think ? 😃
For renderTurboStreamListen
function, https://github.com/symfony/ux/blob/3551bc2f664f89f8af8bcd0b5dee31916f2e6b9c/src/Turbo/src/Bridge/Mercure/TurboStreamListenRenderer.php#L45-L67
I thought about this:
public function renderTurboStreamListen(Environment $env, $topics): string
{
$topicsValue = [];
foreach ($topics as $topic) {
if (\is_object($topic)) {
$class = $topic::class;
if (!$id = $this->idAccessor->getEntityId($topic)) {
throw new \LogicException(\sprintf('Cannot listen to entity of class "%s" as the PropertyAccess component is not installed. Try running "composer require symfony/property-access".', $class));
}
$topicsValue[] = \sprintf(Broadcaster::TOPIC_PATTERN, rawurlencode($class), rawurlencode(implode('-', $id)));
} elseif (!preg_match('/[^a-zA-Z0-9_\x7f-\xff\\\\]/', $topic) && class_exists($topic)) {
// Generate a URI template to subscribe to updates for all objects of this class
$topicsValue[] = \sprintf(Broadcaster::TOPIC_PATTERN, rawurlencode($topic), '{id}');
}
}
$stimulusAttributes = $this->stimulusHelper->createStimulusAttributes();
$stimulusAttributes->addController(
'symfony/ux-turbo/mercure-turbo-stream',
['topic' => $topicsValue, 'hub' => $this->hub->getPublicUrl()]
);
return (string) $stimulusAttributes;
}
For twig, it could be this:
<div {{ turbo_stream_listen(['topic-1', 'App\\Entity\\Book', 'book']) }}></div>
And then you just have to modify the turbo-stream data controller to loop over the topics.
What do you think?
Hi! First thanks for turbo and mercure integration, i am playing with it for last several days and it is awesome!
I am struggling with finding a way, how to subscribe to multiple topics using
turbo_stream_listen()
in twig and after some digging around, it seems that it is not currently supported.I can do it this way, but i would love to avoid writing javascript in twig (as documented in https://symfony.com/doc/current/mercure.html#subscribing):
But by doing this i am loosing a lot of comfort.
What i tried:
That
a&topic=b
variant was my favourite that it would work, but unfortunately it escapes the&
so final URL is like this, which is why it is treated as single topic:What i am actually trying to achieve is this hub url with single
turbo_stream_listem()
:My current solution is to:
Which results into two connections to hub and i believe it would be more efficient to have one connection with two subscriptions.
I could probably solve this by writing my own stimulus controller (inspired by turbo_stream_controller.js).
My idea is to update
Symfony\UX\Turbo\Bridge\Mercure\TurboStreamListenRenderer