Scroll action in PureScript Halogen
I am using purescript-halogen and I want to scroll to the bottom of the div when the child component message has been detected. However, it looks like there is no scrolling motion control in the halogen. So how can I scroll to the end of the div?
One solution I believe is that calling another, not Halogen, process from Main when the event is caught. I'm not sure if this solution is not bad.
source to share
Adjusting the scroll position is done only with the usual DOM rendering-oriented node functionality.
To do this, you need to add a property ref
in HTML-DSL to the node you want to loop through:
-- Define this in the same module as / in the `where` for a component
containerRef ∷ H.RefLabel
containerRef = H.RefLabel "container"
-- Use it with the `ref` property like so:
render =
HH.div
[ HP.ref containerRef ]
[ someContent ]
And then in eval
for the component, you can get the actual DOM element created with getHTMLElementRef
and then update the scroll position on that:
eval (ScrollToBottom next) = do
ref ← H.getHTMLElementRef containerRef
for_ ref \el → H.liftEff do
scrollHeight ← DOM.scrollHeight el
offsetHeight ← DOM.offsetHeight el
let maxScroll ← scrollHeight - offsetHeight
DOM.setScrollTop maxScroll el
pure next
Below are snippets from some real world code that does something like this, so should do the trick!
source to share
Essentially the same answer as fooobar.com/questions/2415666 / ... , but I had a hard time finding different imports:
import Halogen as H
import Halogen.HTML as HH
import Data.Foldable (for_)
import DOM.HTML.Types (htmlElementToElement)
import DOM.Node.Element (scrollHeight, setScrollTop)
import DOM.HTML.HTMLElement (offsetHeight)
...
-- Define this in the same module as / in the `where` for a component
containerRef ∷ H.RefLabel
containerRef = H.RefLabel "container"
-- Use it with the `ref` property like so:
render =
HH.div
[ HP.ref containerRef ]
[ someContent ]
...
eval (ScrollToBottom next) = do
ref <- H.getHTMLElementRef containerRef
for_ ref $ \el -> H.liftEff $ do
let hel = htmlElementToElement el
sh <- scrollHeight hel
oh <- offsetHeight el
let maxScroll = sh - oh
setScrollTop maxScroll hel
pure next
source to share