bigskysoftware / bigskysoftware/htmx

htmx.ajax requests promise fulfilled too early

Open
#2,839 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
49.4k
Forks
1.7k
Avg merge
3d 22h
Merged PRs (30d)
30

Description

When using htmx.ajax the returned promise is fulfilled before htmx finishes all DOM manipulations.

Here is an example. One would think that the displayed box is blue after everything finished but it is red. Why? Because htmx copies some classes from the old elements to the new ones after the ajax promise is fulfilled.
1. html is loaded and the box is gray
2. js gets executed and the ajax call is made
3. the ajax promise is fulfilled and the color is switched to blue
4. htmx calls some settle methods and overwrites the changes made in step 3.
5. the box has the wrong color

`index.html`
```html



Basic example







window.htmx.ajax("GET", "./main.html", {
source: "#main",
target: "#main",
swap: "innerHTML",
}).then(() => {
console.log("promise resolved");
document.getElementById("box").classList.remove("bg-red-200");
document.getElementById("box").classList.add("bg-blue-200")
});

```

`main.html`
```html


```

My current workaround is using `htmx:afterSettle`, but this is inconvenient, because the data flow is now broken and we need to associate the data with the corresponding settle event.

```js
var boxState;

document.addEventListener("htmx:afterSettle, (e) => {
if (e.detail.pathInfo.requestPath === "./main.html") {
// do stuff with boxState
}
});

// somewhere else
boxState = state;
window.htmx.ajax("GET", "./main.html", {
source: "#main",
target: "#main",
swap: "innerHTML",
});
```

Here the log with `htmx.logAll()`:
```diff
htmx.esm.js:895 htmx:confirm

​…​
​ {target: div#container, elt: div#container, path: './container.html', verb: 'get', triggeringEvent: undefined, …}
htmx.esm.js:895 htmx:configRequest
​…​
​ {boosted: undefined, useUrlParams: true, formData: FormData, parameters: Proxy(FormData), unfilteredFormData: FormData, …}
htmx.esm.js:895 htmx:validateUrl
​…​
​ {url: URL, sameHost: true, boosted: undefined, useUrlParams: true, formData: FormData, …}
htmx.esm.js:895 htmx:beforeRequest
​…​
​ {xhr: XMLHttpRequest, target: div#container, requestConfig: {…}, etc: {…}, boosted: undefined, …}
htmx.esm.js:895 htmx:beforeSend
​…​
​ {xhr: XMLHttpRequest, target: div#container.htmx-request, requestConfig: {…}, etc: {…}, boosted: undefined, …}
htmx.esm.js:895 htmx:xhr:loadstart
​…​
​ {lengthComputable: false, loaded: 0, total: 0, elt: div#container.htmx-request}
htmx.esm.js:895 htmx:beforeProcessNode ​​…​​​​​
​…​
​​​​​ {elt: body.h-full.w-full.m-0}
htmx.esm.js:895 htmx:load ​…​​ {elt: body.h-full.w-full.m-0}
htmx.esm.js:895 htmx:xhr:progress
​…​
​ {lengthComputable: true, loaded: 103, total: 103, elt: div#container.htmx-request}
htmx.esm.js:895 htmx:beforeOnLoad
​…​
​ {xhr: XMLHttpRequest, target: div#container.htmx-request, requestConfig: {…}, etc: {…}, boosted: undefined, …}
htmx.esm.js:895 htmx:beforeSwap
​…​
​ {shouldSwap: true, serverResponse: '\x3Cscript type="module" src="/@vite/client">\x3C/script…iv id="box" class="w-64 h-32 bg-red-200">\r\n', isError: false, ignoreTitle: undefined, selectOverride: undefined, …}
htmx.esm.js:895 htmx:beforeCleanupElement
​ {elt: div#box.w-64.h-32.bg-gray-200}
htmx.esm.js:895 htmx:beforeCleanupElement " " {elt: text}
htmx.esm.js:895 htmx:beforeCleanupElement " " {elt: text}
htmx.esm.js:895 htmx:afterSwap
​…​
​ {xhr: XMLHttpRequest, target: div#container.htmx-request.htmx-settling, requestConfig: {…}, etc: {…}, boosted: undefined, …}
htmx.esm.js:895 htmx:afterRequest
​…​
​ {xhr: XMLHttpRequest, target: div#container.htmx-settling, requestConfig: {…}, etc: {…}, boosted: undefined, …}
htmx.esm.js:895 htmx:afterOnLoad
​…​
​ {xhr: XMLHttpRequest, target: div#container.htmx-settling, requestConfig: {…}, etc: {…}, boosted: undefined, …}
- renderer.ts:19 promise resolved
htmx.esm.js:895 htmx:xhr:loadend
​…​
​ {lengthComputable: true, loaded: 103, total: 103, elt: div#container.htmx-settling}
htmx.esm.js:895 htmx:beforeProcessNode ​​ {elt: script}
htmx.esm.js:895 htmx:load ​​ {elt: script}
htmx.esm.js:895 htmx:beforeProcessNode
​ {elt: div#box.w-64.h-32.bg-red-200}
htmx.esm.js:895 htmx:load
​ {elt: div#box.w-64.h-32.bg-red-200}
htmx.esm.js:895 htmx:afterSettle
​…​
​ {xhr: XMLHttpRequest, target: div#container, requestConfig: {…}, etc: {…}, boosted: undefined, …}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.