htmx
htmx copied to clipboard
An out-of-order refresh bring old data(?)
I have an issue with users with slow connections. They are updating invoices in their phones (android) and sometimes the values are lost or overwritten.
<input type="text" id="discount" name="discount" inputmode="decimal" hx-post="" hx-trigger="keyup changed delay:2s" hx-swap="outerHTML" hx-target="#content" hx-select="#content">
So, this is the flow of actions:
- Enter a value like 23. It gets sent to the server
- Now remove it or change it (23.3). It gets sent to the server
- Sometimes it gets rewritten into 23
- Then the server has responded with 23 then 23.3
I attach a video of the issue: https://user-images.githubusercontent.com/238983/133696804-155505bd-600e-441d-9263-443b68b1d44c.mp4
It looks like you have two elements making submissions and having requests in flight at the same time, and as they compete to update one or the other wins.
The way to synchronize the two is to move the event up the DOM to a single element that issues requests on behalf of both elements:
<div hx-post="/whatever" hx-trigger="changed from:.watch" ... >
...
<input class="watch" ...>
...
<input class="watch" ...
...
</div>
Now the outer div is responsible for issuing the request and will properly enqueue new updates from the user while an existing request is in flight, thus serializing them.
Ok, this conflict with the other triggers:
When I put this into the form tag:
<form id="app" name="Form" method="POST" hx-trigger="keyup changed delay:2s from:.input">
<content id='content'>
<input type="text" id="qty" name="qty" class="input" hx-post="" hx-swap="outerHTML" hx-target="#content" hx-select="#content">
<input type="text" id="discount" name="discount" class="input" hx-post="" hx-swap="outerHTML" hx-target="#content" hx-select="#content">
</content>
</form>
It only requests when the input gets out of focus, instead of on key change like before. I try moving around to the parent but it not fire, it needs to stay in the input. So is not clear (to me) how all the options interact.
I think the problem here is a subtle one with changed
, which applies to the form
rather than the target element in this case.
If you remove that, it should work.
Sorry for the delay on this.
Not work with the change. Same behavior. I also with only changed but same.
P.D: Is possible to control this by js? I have problems with users because this is altering the input data and is a bad thing when invoicing...
Also keyup changed delay:1s
means the delay is applied to both events? Or could be the delay is only for the last?
P.D: Removing the delay make the problem more evident.
Ok, after looking at the code and remembering I have reported this issue, I do this change:
function handlePreservedElements(fragment) {
forEach(findAll(fragment, '[hx-preserve], [data-hx-preserve]'), function (preservedElt) {
var id = getAttributeValue(preservedElt, "id");
var oldElt = getDocument().getElementById(id);
if (oldElt != null) {
//preservedElt.parentNode.replaceChild(oldElt, preservedElt);
preservedElt.value = oldElt.value;
}
});
}
This keeps the value to be replaced and avoids "jump" out of focus. Maybe add an option to hx-preserve for values?