data-poll cannot be set conditionally
Chances are this is not really a bug, but simply a limitation of Live Components or my lack of understanding how things work under the hood.
I'm using a UX Live Component to "wait" for a certain information to become available on the backend.
<div
{{ attributes }}
data-poll
>
{% if this.info is not null %}
The info is now available: {{ this.info }}
{% else %}
The info is not yet available, please wait...
{% endif %}
</span>
This works beautifully, and hats off for the awesome design and implementation of the UX ecosystem!
However, once the information has become available, it's kind of a waste to keep polling for it, as the information will not change further.
Right now, polling simply continues, wasting the end user's bandwidth by making requests whose result is always the same ad infinitum.
My naïve approach was to try something like this:
<div
{{ attributes }}
{% if this.shouldPoll %}
data-poll
{% endif %}
>
{% if this.info is not null %}
The info is now available: {{ this.info }}
{% else %}
The info is not yet available, please wait...
{% endif %}
</span>
with shouldPoll changing from true to false in the accompanying component class. However, this doesn't work - state changes are only reflected within the outermost component DOM element but not on that element itself. And as data-poll can only live on this outermost element, I seem to be out of luck.
Maybe someone can point me in the right direction. I've already read the source (mainly live_controller.ts), but could not reverse-engineer an approach from this.
Hey @manuelkiessling!
Thanks for the nice words! And yes, I would have tried the same solution that you did - this solution, imo should work. And so if it doesn't, that is indeed a bug. However, I had thought this does work as you described. live_controller.ts contains a mutation observer that watches for attribute changes on the outer element: https://github.com/symfony/ux/blob/5893aca1b239a48b97b09fc1c6316b65f9d2d749/src/LiveComponent/assets/src/live_controller.ts#L988-L995
When any attributes change, initiatePolling() is called which stops any polling and restarts it. But now that data-poll would be gone, it should not restart: https://github.com/symfony/ux/blob/5893aca1b239a48b97b09fc1c6316b65f9d2d749/src/LiveComponent/assets/src/live_controller.ts#L794-L798
So, questions:
A) After the poll does its work and shouldPoll is now false, do you see that the outer div is missing data-poll? Or do you still see the attribute?
B) Can you tell me what you mean by this?
However, this doesn't work - state changes are only reflected within the outermost component DOM element but not on that element itself
Btw, another way to see if live_controller.ts is behaving correctly would be to literally (a) refresh then (b) manually remove the data-poll element via your browser's debugging tools. If all works well, simply doing that should stop the polling.
Cheers!
Hey @weaverryan, thanks for looking into this.
The
state changes are only reflected within the outermost component DOM element but not on that element itself
part is simply my implicit assumption that a UX Live Component's outermost DOM element would act as some kind of "static" container that sets the component up on initial load, creating a kind of canvas within which all the contained DOM elements can dynamically change by fetching updated HTML from the backend, but that this outermost DOM element itself would not be able to be changed subsequentially. As in "it reloads its contents, but it doesn't reload itself as a whole".
Not sure why I made this assumption, but glad to hear that this is in fact not true.
It thus seems that my problem lies within the Component class, not the template. I will investigate further and report back.
Closing this - but please re-open if you see that this is indeed a problem