-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ajax request sometimes triggered twice with hx-trigger="load" in web components #2973
Comments
Interesting issue, in this case I think you might want to define a delay to postpone the load trigger, with for example Though I agree that ideally you shouldn't need to do that, htmx should handle it itself by default. I'd consider this as a bug, so feel free to explore whatever way feels best for you to fix the issue and submit a bugfix PR @basvk. Just keep in mind the usual constraints (no breaking change, add tests to prove the issue happens without your fix, then doesn't happen anymore with your fix) If you go with the classlist approach you did in the commit you referenced, you'll likely want to handle other htmx classes ( |
Adding the delay is a nice quick workaround for anyone hitting this issue, thanks! For a more robust fix, maybe the hashing logic needs to be revised? It seems the value of initHash is only used in initNode (its existence is used in maybeReveal but not its exact value). Looking at what happens in initNode, only a limited set of element attributes have influence on its behavior. Any other attribute changing does not influence its result, so technically these could be ignored when calculating the attributesHash. For as far as I can see these attributes are used by initNode (and functions called from within initNode):
If we base the calculation of the initHash on these attributes only, we forego unnecessary re-initialization when irrelevant attributes are changed between processNode calls (quite a normal occurrence when using web components). Do you see any problems with this approach (other than the amount of code slightly increasing)? |
You're right @basvk , the purpose of the hash is to determine whether an element's specs changed (in which case we should reprocess it), for example if its I like your approach, except the amount of hardcoded strings it's going to add 😆 I'm also a bit worried that this is the kind of function we may forget behind if/when adding new attributes in the future that should be hash-changing. From the top of my head I think it's safe to just process all htmx-related attributes here (to ease the processing & avoid future omissions), and to do a simple prefix check as we have a very specific prefix for our attributes anyway, that would very unlikely collide with anyone else's code Let me know! |
If we limit the attributesHash to only hx- and data-hx attributes, changes to the action, form, href, method, target and type attributes on an existing element will not result in a change of the triggerHandler for that element anymore. This could impact users (example: existing hx-boosted I took a step back and I'm realizing the real issue is that hx-trigger="load" should only be handled when an element has no initHash set at all (meaning this is the first time htmx ever sees it). If it has an initHash, and the attributes changed, it should not handle hx-trigger="load", because the element was already loaded. Refining the attributeHash calculation actually does not fully fix that, if I change a hx- attribute on an existing element that has So I think I'll leave the attributeHash calculation as it is now (the performance benefit alone does not seem compelling enough to make any changes). |
I went ahead and created a PR. |
I'm working with web components (with lit.dev) and using htmx to populate or replace them in the page. This saves me from writing a lot of business logic and networking code in the frontend. I'm not using shadow dom, and in general it works pretty well. I'm calling
htmx.process
inside the components on update.Sometimes I'm seeing duplicate ajax requests occurring on (nested) elements with
hx-trigger="load"
, mainly on Safari 17.6.In my case the response is swapped in with
hx-swap="afterbegin"
, causing duplicated children in the web component.The element triggering the load is in a nested hierarchy. Top nodes do not show this behaviour.
Here-in lies the issue: in a regular web page
htmx.process
(or ratherprocessNode
) after initial page load is only called on the body, running initNode on all child elements with htmx attributes once.With web components however, htmx.process is called for every web component, and every web component nested within it. This means children are visited multiple times, once for every parent component that calls htmx.process plus the child itself.
Luckily, this by itself is not a problem, because initNode checks if the node already has a corresponding initHash value and will not init again in that case.
However, the initHash is calculated from the node's attributes. Between the different calls to htmx.process from each webcomponent, the attributes sometimes do change, causing initHash to differ and to call initNode again on a node.
In my scenario between calls to htmx.process, the element (when visited during
processNode
on a parent element) with hx-trigger="load" starts an ajax request and gets class="htmx-request" set. This alters the attributes, meaning that the element's initHash is not correct anymore for the attributes. This results in the node being initialized again during the next call to htmx.process (on another parent or itself) and starting a second ajax request...Now I've solved this particular case by adding a check to not initialize if the node has
htmx-request
in its classList (see this commit: master...basvk:htmx:fix-double-load - let me know if you'd like a pull request), but I'm not sure if there are other cases where multiple calls to htmx.process might cause these kind of issues.Maybe initHash should be based on a subset of attributes, or calculated in a different way when dealing with web components? What is your opinion?
The text was updated successfully, but these errors were encountered: