When I working with HTMX, I should remember using htmx
Events instead using native JavaScript Events to listen some event when DOM is swapped!
The Cash Case Is #
When I need to my Tabs Markup is remembering the last tab open. In my primitive experience is using javascript DOMContentLoaded
is enough.
1document.addEventListener("DOMContentLoaded", function() {
2 var lastTab = localStorage.getItem("lastTab");
3 if (lastTab) {
4 var tab = document.querySelector('input[name="view_tabs"][aria-label="' + lastTab + '"]');
5 if (tab) {
6 tab.checked = true;
7 tab.dispatchEvent(new Event('change'));
8 }
9 }
10
11 var tabs = document.querySelectorAll('input[name="view_tabs"]');
12 tabs.forEach(function(tab) {
13 tab.addEventListener('change', function() {
14 localStorage.setItem("lastTab", this.getAttribute('aria-label'));
15 });
16 });
17});
But it's wrong! Stupid! Yes I am.
Why? #
The DOMContentLoaded
event fires when the HTML document has been completely parsed, and all deferred scripts (<script defer src="…">
and <script type="module">
) have downloaded and executed. It doesn't wait for other things like images, subframes, and async scripts to finish loading.
DOMContentLoaded
does not wait for stylesheets to load, however deferred scripts do wait for stylesheets, and the DOMContentLoaded event is queued after deferred scripts. Also, scripts which aren't deferred or async (e.g. <script>
) will wait for already-parsed stylesheets to load.
A different event, load, should be used only to detect a fully-loaded page. It is a common mistake to use load where DOMContentLoaded
would be more appropriate.
This event is not cancelable.
Source: MDN Web Docs - DOMContentLoaded
But, in HTMX Event - htmx:load
#
This event is triggered when a new node is loaded into the DOM by htmx. Source: htmx:load
So, The Solving Cash Case #
Just change the DOMContentLoaded
to htmx:load
1document.addEventListener("htmx:load", function() {
2 var lastTab = localStorage.getItem("lastTab");
3 if (lastTab) {
4 var tab = document.querySelector('input[name="view_tabs"][aria-label="' + lastTab + '"]');
5 if (tab) {
6 tab.checked = true;
7 tab.dispatchEvent(new Event('change'));
8 }
9 }
10
11 var tabs = document.querySelectorAll('input[name="view_tabs"]');
12 tabs.forEach(function(tab) {
13 tab.addEventListener('change', function() {
14 localStorage.setItem("lastTab", this.getAttribute('aria-label'));
15 });
16 });
17});
🛑 Case closed!