htmx icon indicating copy to clipboard operation
htmx copied to clipboard

Migrate from v1.9.12 to v2.0.0 breaks some layout and behaviour of a dropdown button

Open maj2c opened this issue 1 year ago • 7 comments

Hi, After I updated the htmx version from 1.9.12 to 2.0.0 I get layout issue (see screenshots below) but I can not pin point the CSS/class causing this or get overridden after the swap of the element content. Beside the above I noticed that a dropdown button for switching page language does not work (no click event is fired) when the v2.0.0 is used. There is no error in the console. In the project I use Syncfusion components, bootstrap and htmx. Any one has an idea how to trace / pin point the cause or facing similar behaviour?

Layout with version 1.9.12: htmx_v1_9_12

Layout with version 2.0.0: htmx_v2_0_0

maj2c avatar Jun 28 '24 09:06 maj2c

Hey, I'm afraid we'll need more information to be able to help you! Htmx is a JS library and except the temporary classes it adds during the requests processes, doesn't do anything regarding CSS so that sounds very strange. Is this table in the initial page or does it get swapped in by htmx after a certain action ? If the latter, could you provide the HTML snippets fed to htmx in both cases and the actual output in the DOM? For example, htmx 2 uses template fragments, which was previously an opt-in parameter in htmx 1 (see htmx.config.useTemplateFragments), so I'm thinking it might be a related issue?

Telroshan avatar Jun 29 '24 09:06 Telroshan

Hi, Thank you for the reply and looking into this issue. The main div gets swapped on every menu click. I compared the response result of the menu click and they are the same. I did a console.log(htmx.config.useTemplateFragments) got undefined. Forced it to false but that did not change the behaviour. Added the but that did not help. Compared the DOM of first visit of a menu against the second click of the menu and I see they are the same except for missing syncfusion grid css classes. Besides that, the row click event does not fire when the grid is loaded for the second time.

At first I thought it is an issue with the grid, now I see any div content swapped with data containing the same syncfusion element such as grid or dashboard, the layout is broken and the component events do not fire.

I tried to get you the requested snippets and actual output in the DOM, but I am not sure I am allowed to post it in here. Will try to explain the flow and behaviour, hope this helps: There is a menu div, all the menu items swap the main div content. The data swapped may contain (A) plain text, (B) dashboard component or (C) grid component. When I navigate from menu A to B or C layout is fine. When navigating from B to C the layout is fine. But, from B to B or C to C the layout and events are broken.

Thank you in advance for looking into this issue.

maj2c avatar Jun 30 '24 13:06 maj2c

Thanks for the details. So, if I understood correctly, when going from C to C let's say, the HTML is exactly the same, except the CSS classes aren't there anymore?

  • Are those CSS classes in the initial HTML of your request's response? I.e., do the classes disappear between the moment your request returns a response, and the moment htmx inserts the elements into the DOM?
  • Or are those CSS classes added in runtime by that library?

I'm thinking of 2 ideas that you'd have to check for yourself, just plain guesses here:

  • Could it be that your library "initializes" its components in some way through JS and isn't doing anymore, thus not adding classes and not binding listeners? Could you try manually calling that initialization function if it's exposed, after the swap? (similarly to htmx.process that we have the same issue with ; if people insert elements in the DOM not using htmx, this function needs to be called to have htmx process those elements. Could be the same with the library you're using here?)
  • Try copying the HTML of your response and insert that manually into the DOM using your browser's developer tools (plain HTML edit on the document). Just to see how it behaves when not using htmx at all. If the same issue happens, then it's likely that either there's an initialization issue as per the previous suggestion, or an issue with the HTML fragment itself (maybe some difference that you would have missed)

Hope this helps, let me know!

Telroshan avatar Jul 01 '24 07:07 Telroshan

Hi again,

Q: Are those CSS classes in the initial HTML of your request's response? A: No, they get added automatically from Syncfusion component initialisation. I have attached a file with the HTML snippert and the JS functions called from own global/central JS file.

I tried to add the attached HTML snippert manually into the DOM as you suggested, the Syncfusion component (in this case the grid) did not get initialise. No errors in the console.

After reviewing the hx-swap configuration I came across htmx.config.defaultSettleDelay. I have forced it on 5000 and did the test again and I found out within the 5 seconds the layout is correct and the event listeners working too. Once the settleDelay is timed out the grid layout changes and listeners do not work anymore. There is no errors in console. I confirmed that the data is not from cache by changing the values in database before requesting the html snippert.

Thus, maybe something changed between version 1.9.12 and 2.0.0 regarding the settle logic?

HTML_snippert_js_functions.txt

maj2c avatar Jul 01 '24 15:07 maj2c

Hmmm looking at the code, it seems like a typical settling-messing issue, but if it's that, it would be weird that it was working previously as it's a common problem.

To confirm, could you try to set htmx.config.attributesToSettle to an empty array?

By default, the class attribute is "settled" which is this trick that htmx uses to play transitions properly, that clones attributes on an element before and after the swap. In this case, the issue could be that the saved class attribute value is the one before your lib actually does its processing, thus when the settling occurs, the class is reverted to its initial value, i.e. without the lib's classes that were added in the meantime thus out of htmx's sight.

If the above test works (i.e. using an empty htmx.config.attributesToSettle array to disable settling altogether), then it's indeed a timing issue. In the latter case, you might want to use a htmx:afterSettle event listener, to call your sd_sPrepareAndAddTheMainGrid and sd_sRowSelectedOrDeselected functions, instead of calling them in this inline script which would mess up timings. The goal here would be to wait for htmx to settle the element before initializing your component, ensuring no overlap occurs. Of course, if you don't care about CSS transitions at all here, you might just as well disable setting altogether, that's also an option!

Hope this helps!

Telroshan avatar Jul 01 '24 16:07 Telroshan

Thank you Telroshan for your clear explanation and support. Setting the htmx.config.attributesToSettle to an empty array resolved the issue. I did not notice any CSS transitions drawback/missing. Thus, will keep it that way for the time being.

I am puzzled too regarding why it is working in v1.9.12 but not v2.0.0, clearly there is a conflict between HTMX and Syncfusion in the way I am using it. I wonder if they use/refer older version of HTMX in their lib and that causing conflict :) Because, the DropDownButton component used for switching page language does not work with v2.0.0 even with empty htmx.config.attributesToSettle. I resolved that by using a different component.

maj2c avatar Jul 02 '24 07:07 maj2c

Setting the htmx.config.attributesToSettle to an empty array resolved the issue

Good to hear! So that's indeed a normal situation ; since htmx settles attributes, you have 2 options available;

  • Disabling settling (which is what you just did), which has the drawback of potentially messing up CSS transitions (but as you don't use them here, it's fine)
  • Or, run your custom inlined javascript in a htmx:afterSettle event listener rather than at the root of the swapped <script> tag, to make sure no overlap/conflict occurs with htmx

For the record, it should have not been working in htmx 1.9.12 either as it's been a common gotcha for years now, so make sure you don't rely on such unpredictable behavior anywhere else!

does not work with v2.0.0 even with empty htmx.config.attributesToSettle

Sounds weird! Again, I don't know that lib at all, but it might be an issue due to how you wire htmx and that lib together, feel free to share some code if you'd want to investigate!

Telroshan avatar Jul 02 '24 07:07 Telroshan