htmx
htmx copied to clipboard
htmx.values() should include hx-vals and not just form component values
What I'm trying to do:
When the user clicks a button, a popup should be rendered (using Tippy.js) and the ajax response should be swapped into the popup.
I first went down the path of calling a custom JS function on-click, which would use htmx.ajax(). Where I got stuck is that I needed to pass context variables to the ajax call. I thought that htmx.values() would include the values present in hx-vals but it does not, and I confirmed via the source code.
So this ticket is to request for either htmx.values() to include the hx-vals or a new public API to surface this.
That said, I managed to find a workaround - and possibly a much more elegant approach, because the HTML can be idiomatic htmx, and we intercept the beforeRequest event to do the special popup handling. The advantage here is that all the context values are available, including the hx-vals in requestConfig.parameters.
For the reference of others and also for my learning - I would really appreciate some feedback on this approach. My main questions are:
- Is the
htmx.process()used at the right time, I confirmed that it is doing what is expected, and without it the hx-* in the popup don't work - is the usage of the
handlerfunction, optimal, I am assuming htmx will not attempt to swap anything and leave everything to the handler - is
event.preventDefault()the right way to "cancel" the htmx request - do you have any other comments or suggestions to improve this
htmx.on('htmx:beforeRequest', (event) => {
let target = event.detail.elt;
if (target.classList.contains('use-tippy')) {
event.preventDefault();
if (target._tippy) {
target._tippy.show();
} else {
let config = event.detail.requestConfig;
let instance = tippy(target, {
trigger: 'manual',
allowHTML: true,
interactive: true,
content: 'Loading...'
});
htmx.ajax(config.verb, config.path, {values: config.parameters, handler: (src, dest) => {
let temp = document.createElement('div');
temp.innerHTML = dest.xhr.responseText;
htmx.process(temp);
instance.setContent(temp);
}});
instance.show();
}
}
});
Something else I ran into is that htmx.ajax() seems to always assume that the body is the "target" no matter what. This was causing all my ajax indicators on the page to become visible. I had to do this to work-around. let me know if you need more info.
body.htmx-request .my-indicator {
display: none;
}
.htmx-request .my-indicator {
display: inline-block;
}