Closed renardeinside closed 6 months ago
do you have hx-swap
set to morph:innerHTML
? I see hx-ext="morph:innerHTML"
which isn't the right syntax:
https://github.com/bigskysoftware/idiomorph?tab=readme-ov-file#htmx
Thanks for the note @1cg - I've fixed the hx-swap
property but still didn't get to the expected result:
<div id="schorle-event-handler" hx-ws="connect:/_schorle/events" hx-ext="morph">
<div id="schorle-page" hx-swap="morph:innerHTML" class="space-y-4 h-screen flex flex-col justify-center items-center">
<button id="schorle-button-4380719632" hx-ws="send" hx-swap="morph:innerHTML" class="btn btn-primary">Increment</button>
<button id="schorle-button-4380719392" hx-ws="send" hx-swap="morph:innerHTML" class="btn btn-secondary">Decrement</button>
<p id="schorle-p-4380719232" hx-swap="morph:innerHTML">Counter is 0</p>
</div>
</div>
htmx
websocket when a click on increment
happens is as follows:
<div id="schorle-event-handler" hx-ws="connect:/_schorle/events" hx-ext="morph">
<div id="schorle-page" hx-swap="morph:innerHTML" class="space-y-4 h-screen flex flex-col justify-center items-center">
<button id="schorle-button-4380719632" hx-ws="send" hx-swap="morph:innerHTML" class="btn btn-primary">Increment</button>
<button id="schorle-button-4380719392" hx-ws="send" hx-swap="morph:innerHTML" class="btn btn-secondary">Decrement</button>
<p id="schorle-p-4380719232" hx-swap="morph:innerHTML">Counter is 1</p>
</div>
</div>
As you can see the buttons are identical, all of the payloads are identical, the only change is the inner HTML of p
.
I expected that buttons will not be re-loaded, but seems like they are (animation is triggered on both of them).
My idea is that I would like to avoid calculating the difference between previous and new page state on the client. I would prefer to send the whole HTML to the client as a message and let idiomorph
merge them. Assuming that all elements are indexed with ids, I was expecting that it should be a trivial operation.
i would run an uncompressed version of htmx & idiomorph and ensure that the right swap is being used.
you can set a breakpoint here:
@1cg I'm a bit far from JS and frontend - could you please be a bit specific about "running an uncompressed version"? I've tried this:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Schorle</title>
<link href="https://cdn.jsdelivr.net/npm/daisyui@4.4.22/dist/full.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://github.com/bigskysoftware/htmx/blob/v1.9.10/src/htmx.js"></script>
<script src="https://github.com/bigskysoftware/idiomorph/blob/v0.3.0/src/idiomorph-htmx.js"></script>
<script src="https://github.com/bigskysoftware/idiomorph/blob/v0.3.0/src/idiomorph.js"></script>
</head>
But I'm not entirely sure if it properly initializes the relevant libraries.
Okey, I've just downloaded all deps and serve them locally:
wget https://raw.githubusercontent.com/bigskysoftware/htmx/v1.9.10/src/htmx.js
wget https://raw.githubusercontent.com/bigskysoftware/idiomorph/v0.3.0/src/idiomorph.js
wget https://raw.githubusercontent.com/bigskysoftware/idiomorph/v0.3.0/src/idiomorph-htmx.js
When I trigger the event, I see the following error in the log:
htmx.js:2211 TypeError: Cannot read properties of undefined (reading 'swapStyle')
at Object.isInlineSwap (idiomorph-htmx.js:15:27)
at isInlineSwap (htmx.js:784:35)
at htmx.js:822:30
at forEach (htmx.js:405:21)
at oobSwap (htmx.js:815:17)
at WebSocket.<anonymous> (htmx.js:1666:21)
It comes from htmx.js
. Not sure if it's an issue of my setup, or it's the relevant problem.
Despite the error, the update happens, but with the issue above - still it's a full-scale update and not just a morph of the relevant fields.
Okay, so I did some high-level debugging and found the following:
// file: htmx.js, lines start from 779
function isInlineSwap(swapStyle, target) {
console.log(`isInlineSwap: swapStyle: ${swapStyle}, target: ${target}`);
var extensions = getExtensions(target);
for (var i = 0; i < extensions.length; i++) {
var extension = extensions[i];
try {
if (extension.isInlineSwap(swapStyle)) {
return true;
}
} catch(e) {
logError(e);
}
}
return swapStyle === "outerHTML";
}
this function depends on the value of var swapStyle
defined in line 804. The default value is outerHTML
, which cannot be properly parsed in idiomorph-js
:
function createMorphConfig(swapStyle) {
if (swapStyle === 'morph' || swapStyle === 'morph:outerHTML') {
return {morphStyle: 'outerHTML'}
} else if (swapStyle === 'morph:innerHTML') {
return {morphStyle: 'innerHTML'}
} else if (swapStyle.startsWith("morph:")) {
return Function("return (" + swapStyle.slice(6) + ")")();
}
}
Monkey-patch is to set the value of var swapStyle
to morph
, but I'm unsure about the proper patch.
I found a way to fix the issue - just put hx-swap-oob="morph"
onto the relevant object. I must admit that it was quite hard to debug and identify, and it kinda makes sense, but still would be quite convenient to but such a property to htmx.config.
Hi team,
I'm trying to use
idiomorph
in combination withhtmx
. Unfortunately, it behaves quite strangely, generating a full rewrite of an element, even though there is just one class changed in one of the children.Here is an example:
State of the element before the update:
I'm sending a ws message with an update, it looks as follows:
Scripts in
head
are:As you can see all indexes are same, the only change is the class attribute of the second button.
However, I see that a full rewrite has been generated (both buttons are animated as on their first load):