I have a div element where it is scrollable
<script>
let scrollBoxObj;
$: scrollBoxObj = document.getElementById("chat-box");
$: if (!(scrollBoxObj === undefined) && scrollBoxObj.scrollTop < scrollBoxObj.scrollHeight) {
scrollBoxObj.scrollTop = scrollBoxObj.scrollHeight;
}
</script>
<div id="scrollBox" class="h-screen w-auto chat-box border border-orange rounded">
<div id="chat-box" style="margin: 0" class="chat-box">
{#each chatBox as { user, content, type}}
<MessageBox {user} message={content} {type} />
{/each}
</div>
</div>
<style>
.chat-box {
overflow-y: auto;
}
</style>
i am trying to auto scroll down when a new message is added. but it is not reactive. or i didn't understand how reactivity works in svelte. i also tried to assign scrollBoxObj in onMount but it was still the same result didn't work.
In Svelte, the reactivity from $: x = y
kicks in when there is a change on the left side from the equation (the y
-part).
In your code you have
$: scrollBoxObj = document.getElementById("chat-box");
On the left side we have a string ("chat-box") which is a constant and will never change, there is also the document which will also never change, this means the reactivity will not work as you expect.
When working with Svelte using document.getElementById
(or any of the other selector methods) is considered bad practice because you are interacting directly with the DOM, while your DOM should rather be a reflection of your state. In short: don't do it.
Svelte provides you with an easy way to bind a DOM-node (like a div) to a variable by simply adding bind:this={variable}
In your case this would become:
<script>
let scrollbox
</script>
<div bind:this={scrollbox}>
...
</div>
The reactive declaration (the if block) will execute whenever anything inside it changes, which is scrollbox in your case:
$: if (scrollBoxObj && scrollBoxObj.scrollTop < scrollBoxObj.scrollHeight) {
scrollBoxObj.scrollTop = scrollBoxObj.scrollHeight;
}
Just note here again that this will only trigger when scrollbox changes, once it is bound you will not retrigger (for instance when the user scrolls, it will not do anything) for that you should probably use an on:scroll
event.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With