Open unabomber78 opened 1 year ago
That's a very vague description. Did you try the focus scroll setting ?
You are referring to focus-scroll:true described here? https://htmx.org/attributes/hx-swap/ I tried to apply this to my hx-swap-oob="beforeend:#messages" but I get an error in the console.
@unabomber78 mind linking the error ?
I'm sorry, I didn't quite follow you. English is not my native language, so sometimes I use a translator and sometimes I misunderstand my interlocutor. I thought I described my problem in detail, but maybe I did not. I am passing a new message to the message box using hx-swap-oob="beforeend:#messages" I would like to pass also the information that the scroll bar should move to the very bottom after adding a new message. I thought the documentation link I provided in the previous post described how to do what I wanted. But I have not been able to achieve what I want with htmx, although I have already achieved what I need with css.
Hello! I'm also trying to do the same thing, and having similar problems. I'm using a websocket connection to return html wrapped in:
<div id="message-list" hx-swap-oob="beforeend">
{content}
</div>
Like @unabomber78, I would like to scroll to the bottom of the #message-list
div after adding the message. So I tried:
<div id="message-list" hx-swap-oob="beforeend focus-scroll:true">
{content}
</div>
But, unlike @unabomber78, I don't see an error in the browser console. Instead the DOM doesn't get updated with the new HTML.
I've also tried:
<div hx-swap-oob="beforeend:#message-list focus-scroll:true">
{content}
</div>
with the same results. And I tried using "scroll:bottom" instead of "focus-scroll:true" with the same results: no DOM update, and no console messages. Removing "focus-scroll:true" causes the DOM to be properly updated again.
I'm using htmx-1.9.6 with the ws.js extension. I also have Tailwind CSS loaded into the page, if that has any effect. I've tested in Chrome (118.0.5993.70) and Firefox (118.0.2).
Should using "focus-scroll:true" or "scroll:bottom" work here in these cases?
Seeing the same with the sse extension.
<div style="height: 200px; overflow: scroll;" hx-ext="sse" sse-connect="my_url..." sse-swap="message" hx-swap="innerHTML scroll:bottom" ></div>
Events from SSE do get swapped into the div, but no scrolling occurs.
A workaround. Add this to the swap container element. The contents will need to contain some identifiable element you want to scroll to.
hx-on:htmx:after-settle="document.getElementById('some-inner-element').scrollIntoView(false)"
I have a similiar use case to you all that I am struggling to get working. I noticed that there is a console error when I enable logs with htmx.logAll()
and have code that looks like the following:
<div hx-ext="ws" ws-connect="ws://localhost:1323/ws">
<ol id="items" class="list-group list-group-numbered">
</ol>
<form id="input-area" class="input-area" ws-send>
<input name="chat_message" type="text" class="input-field" placeholder="Type a message..."/>
<button class="send-button">Send</button>
</form>
</div>
<ol class="list-group list-group-numbered" hx-swap-oob="beforeend:#items scroll:#items:bottom">
<li class="message incoming" >{contents}</li>
</ol>
Uncaught DOMException: Failed to execute 'querySelectorAll' on 'Document': '#items scroll:#items:bottom' is not a valid selector.
at Object.ye [as oobSwap] (https://unpkg.com/htmx.org@1.9.8:1:8792)
at WebSocket.<anonymous> (https://unpkg.com/htmx.org/dist/ext/ws.js:148:10)
ye @ htmx.org@1.9.8:1
(anonymous) @ ws.js:148
The list is updated with the child <li>
successfully when the scroll:#items:bottom
is not present.
But when the scroll modifier is added, the DOM is not updated, and those console errors start showing.
It seems like the OOB CSS selector separates on a :
, which leaves it trying to find an element named everythingAfterTheColon
After a bit of being nosey, it seems that this is a relatively common pitfall:
The latter issue mentions that he could get around it with an HTML plugin, however, I do not think the classes plugin would aid us here :/
I have a similar problem. I send this over websockets and the following just doesn't update the DOM
<div hx-swap-oob="scroll:bottom swap:.5s innerHTML:#msg-7739b8b5"><p>Text</p>\n</div>
I get the error: Uncaught DOMException: Failed to execute 'querySelectorAll' on 'Document': 'bottom swap:.5s innerHTML:#msg-7739b8b5' is not a valid selector.
I tried different orderings, to no avail. This however works:
<div hx-swap-oob="innerHTML:#msg-7739b8b5"><p>Text</p>\n</div>
@TheQueenIsDead I think the documentation for hx-swap-oob
is a bit misleadding, or at least I made the same assumptions as you did reading it :D
I had a look at the implementation of hx-swap-oob
and it only supports hx-swap
values, so the actual swap strategies with a optional css selector separated by :
. It does not support any additional hx-swap
modifiers like scroll
I have a simple workaround as follows:
<script>
document.addEventListener("htmx:wsAfterMessage", e => {
const messagesDiv = document.getElementById("messages");
messagesDiv.scrollTop = messagesDiv.scrollHeight;
})
</script>
Kind of disappointing, since I was trying to build the entire site without a single line of javascript, but I don't think it's a bad solution for the time being.
Would love to see hx-swap-oob
take hx-swap
modifiers.
Seeing the same with the sse extension.
<div style="height: 200px; overflow: scroll;" hx-ext="sse" sse-connect="my_url..." sse-swap="message" hx-swap="innerHTML scroll:bottom" ></div>
Events from SSE do get swapped into the div, but no scrolling occurs.
+1
A workarround using hyperscript:
<div
id="chatMessagesWrapper"
_="
on load set my scrollTop to my scrollHeight end
on htmx:afterSettle set my scrollTop to my scrollHeight end
on htmx:oobAfterSwap set my scrollTop to my scrollHeight end
"
>
or with js:
document.body.addEventListener("htmx:oobAfterSwap", function (evt) {
const chatWrapper = document.querySelector("#chatMessagesWrapper");
chatWrapper.scrollTop = chatWrapper.scrollHeight;
});
htmx:afterProcessNode can also work.
<script>
window.addEventListener('load', () => {
const messageContent = document.getElementById('content');
setTimeout(() => {
window.scrollTo({
top: messageContent.scrollHeight,
behavior: 'smooth'
});
}, 100);
});
document.body.addEventListener('htmx:wsAfterMessage', (event) => {
const messageContent = document.getElementById('content');
window.scrollTo({
top: messageContent.scrollHeight,
behavior: 'smooth'
});
});
</script>
Is there a way to do this without JavaScript or HyperScript?
I'm also trying to build an entire web app without a single line of JavaScript...
Thats an odd question in a repository related to a javascript library
Thats an odd question in a repository related to a javascript library
That's the whole point and philosophy of HTMX; not having to write JavaScript when using HTMX.
I have a simple workaround as follows:
<script> document.addEventListener("htmx:wsAfterMessage", e => { const messagesDiv = document.getElementById("messages"); messagesDiv.scrollTop = messagesDiv.scrollHeight; }) </script>
Kind of disappointing, since I was trying to build the entire site without a single line of javascript, but I don't think it's a bad solution for the time being.
Would love to see
hx-swap-oob
takehx-swap
modifiers.
Didn't want to use vanilla JS but this worked great, than you.
I used htmx websockets to create the chat and hx-swap-oob="beforeend:#messages" to add a new message to the end of the list. How can i set the scroll bar to bottom after new message. I see in the documentation that there is an option to control the scroll bar using htmx, but it only describes the hx-swap attribute. I've tried applying this to hx-swap-oob, but it doesn't get me anywhere. Am I doing something wrong or is it currently impossible to get the result I want with htmx?